2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Clement DAVID
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
16 package org.scilab.modules.graph.utils;
18 import java.awt.geom.Dimension2D;
19 import java.io.IOException;
20 import java.lang.ref.WeakReference;
22 import java.util.HashMap;
24 import java.util.WeakHashMap;
25 import java.util.logging.Logger;
27 import javax.swing.Icon;
29 import org.apache.batik.bridge.BridgeContext;
30 import org.apache.batik.bridge.DocumentLoader;
31 import org.apache.batik.bridge.GVTBuilder;
32 import org.apache.batik.bridge.UserAgent;
33 import org.apache.batik.bridge.UserAgentAdapter;
34 import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
35 import org.apache.batik.gvt.GraphicsNode;
36 import org.apache.batik.util.XMLResourceDescriptor;
37 import org.scilab.forge.jlatexmath.ParseException;
38 import org.scilab.forge.jlatexmath.TeXConstants;
39 import org.scilab.forge.jlatexmath.TeXFormula;
40 import org.scilab.forge.jlatexmath.TeXIcon;
41 import org.scilab.modules.graph.view.SupportedLabelType;
42 import org.w3c.dom.Document;
44 import com.mxgraph.util.mxUtils;
47 * Utilities functions for ScilabGraph
49 public final class ScilabGraphUtils extends mxUtils {
51 * Cache for the generated SVG components
53 private static Map<URL, WeakReference<GraphicsNode>> generatedSVGComponents = new HashMap<URL, WeakReference<GraphicsNode>>();
55 * Cache for the generated SVG document sizes
57 private static Map<URL, Dimension2D> generatedSVGSizes = new HashMap<URL, Dimension2D>();
60 * Cache for the generated latex icons
62 private static Map<Float, Map<String, TeXIcon>> generatedLatexIcons = new WeakHashMap<Float, Map<String, TeXIcon>>();
65 * Table conversion between escaped/unescaped HTML symbols
67 private static final String[][] HTML_ESCAPE_TABLE = { { "<", "<" }, { ">", ">" }, { "&", "&" }, { """, "\"" }, { "à", "\u00e0" },
68 { "À", "\u00c0" }, { "â", "\u00e2" }, { "ä", "\u00e4" }, { "Ä", "\u00c4" }, { "Â", "\u00c2" },
69 { "å", "\u00e5" }, { "Å", "\u00c5" }, { "æ", "\u00e6" }, { "Æ", "\u00c6" }, { "ç", "\u00e7" },
70 { "Ç", "\u00c7" }, { "é", "\u00e9" }, { "É", "\u00c9" }, { "è", "\u00e8" }, { "È", "\u00c8" },
71 { "ê", "\u00ea" }, { "Ê", "\u00ca" }, { "ë", "\u00eb" }, { "Ë", "\u00cb" }, { "ï", "\u00ef" }, { "Ï", "\u00cf" },
72 { "ô", "\u00f4" }, { "Ô", "\u00d4" }, { "ö", "\u00f6" }, { "Ö", "\u00d6" }, { "ø", "\u00f8" },
73 { "Ø", "\u00d8" }, { "ß", "\u00df" }, { "ù", "\u00f9" }, { "Ù", "\u00d9" }, { "û", "\u00fb" },
74 { "Û", "\u00db" }, { "ü", "\u00fc" }, { "Ü", "\u00dc" }, { " ", " " }, { "®", "\u00a9" }, { "©", "\u00ae" },
75 { "€", "\u20a0" }
79 * Return a cached or a new instance of a {@link GraphicsNode} generated
84 * @return the corresponding graphic node
86 public static GraphicsNode getSVGComponent(URL filename) {
87 WeakReference<GraphicsNode> nodeRef;
90 nodeRef = generatedSVGComponents.get(filename);
91 if (nodeRef != null) {
99 String xmlParser = XMLResourceDescriptor.getXMLParserClassName();
100 SAXSVGDocumentFactory df = new SAXSVGDocumentFactory(xmlParser);
101 Document doc = df.createDocument(filename.toString());
102 UserAgent userAgent = new UserAgentAdapter();
103 DocumentLoader loader = new DocumentLoader(userAgent);
104 BridgeContext ctx = new BridgeContext(userAgent, loader);
105 ctx.setDynamicState(BridgeContext.STATIC);
106 GVTBuilder builder = new GVTBuilder();
108 node = builder.build(ctx, doc);
110 generatedSVGComponents.put(filename, node.getWeakReference());
111 generatedSVGSizes.put(filename, ctx.getDocumentSize());
112 } catch (IOException | NullPointerException e) {
113 Logger.getLogger(ScilabGraphUtils.class.getName()).severe(e.toString());
120 * Get the document size for a given URL.
122 * This method use the Document size cache to get the svg element dimension
123 * and not the real size of the graphical tree.
127 * @return the dimension of the file
129 public static Dimension2D getSVGDocumentSizes(URL filename) {
130 Dimension2D ret = generatedSVGSizes.get(filename);
132 // Generate the GraphicsNode if not available
134 getSVGComponent(filename);
135 ret = generatedSVGSizes.get(filename);
141 * Return a cached or a new instance of a TexIcon generated from the text.
145 * @return the TeXIcon
146 * @throws ParseException
147 * when the text is not a valid formula
149 public static Icon getTexIcon(String text, float size) throws ParseException {
151 String escapedText = SupportedLabelType.Latex.escape(text);
153 Map<String, TeXIcon> iconMap = generatedLatexIcons.get(size);
154 if (iconMap == null) {
155 iconMap = new WeakHashMap<String, TeXIcon>();
156 generatedLatexIcons.put(size, iconMap);
159 icon = iconMap.get(escapedText);
161 TeXFormula tex = new TeXFormula(escapedText);
162 icon = tex.createTeXIcon(TeXConstants.STYLE_DISPLAY, size);
163 iconMap.put(escapedText, icon);
169 * Remove the blank char on the beginning of the sequence. This method
170 * modify the {@link StringBuilder} in place.
175 public static void removeBlanks(StringBuilder seq) {
177 for (i = 0; i < seq.length(); i++) {
178 char car = seq.charAt(i);
179 if (car != ' ' && car != '\n') {
190 * This method modify the {@link StringBuilder} in place.
195 * the beginning index
197 public static void unescape(StringBuilder escapedText, int index) {
198 int start, end, table_index;
200 start = escapedText.indexOf("&", index);
202 end = escapedText.indexOf(";", start);
203 // we don't start from the beginning
204 // the next time, to handle the case of
209 String temp = escapedText.substring(start, end + 1);
210 // search in HTML_ESCAPE_TABLE[][] if temp is there
212 while (table_index < HTML_ESCAPE_TABLE.length) {
213 if (HTML_ESCAPE_TABLE[table_index][0].equals(temp)) {
219 if (table_index < HTML_ESCAPE_TABLE.length) {
220 escapedText.replace(start, end + 1, HTML_ESCAPE_TABLE[table_index][1]);
221 unescape(escapedText, index); // recursive call
229 * This class is a static singleton thus it must not be instantiated
231 private ScilabGraphUtils() {