001/* =================================================== 002 * JFreeSVG : an SVG library for the Java(tm) platform 003 * =================================================== 004 * 005 * (C)opyright 2013-present, by David Gilbert. All rights reserved. 006 * 007 * Project Info: http://www.jfree.org/jfreesvg/index.html 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * JFreeSVG home page: 028 * 029 * http://www.jfree.org/jfreesvg 030 * 031 */ 032 033package org.jfree.svg; 034 035import java.io.BufferedWriter; 036import java.io.File; 037import java.io.FileOutputStream; 038import java.io.IOException; 039import java.io.OutputStream; 040import java.io.OutputStreamWriter; 041import java.nio.charset.StandardCharsets; 042import java.util.function.DoubleFunction; 043import java.util.logging.Level; 044import java.util.logging.Logger; 045import java.util.zip.GZIPOutputStream; 046import org.jfree.svg.util.Args; 047import org.jfree.svg.util.DoubleConverter; 048import org.jfree.svg.util.RyuDouble; 049 050/** 051 * Utility methods related to the {@link SVGGraphics2D} implementation. 052 */ 053public class SVGUtils { 054 055 private SVGUtils() { 056 // no need to instantiate this 057 } 058 059 /** 060 * Returns a new string where any special characters in the source string 061 * have been encoded. 062 * 063 * @param source the source string ({@code null} not permitted). 064 * 065 * @return A new string with special characters escaped for XML. 066 * 067 * @since 1.5 068 */ 069 public static String escapeForXML(String source) { 070 Args.nullNotPermitted(source, "source"); 071 StringBuilder sb = new StringBuilder(); 072 for (int i = 0; i < source.length(); i++) { 073 char c = source.charAt(i); 074 switch (c) { 075 case '<' : { 076 sb.append("<"); 077 break; 078 } 079 case '>' : { 080 sb.append(">"); 081 break; 082 } 083 case '&' : { 084 String next = source.substring(i, Math.min(i + 6, 085 source.length())); 086 if (next.startsWith("<") || next.startsWith(">") 087 || next.startsWith("&") 088 || next.startsWith("'") 089 || next.startsWith(""")) { 090 sb.append(c); 091 } else { 092 sb.append("&"); 093 } 094 break; 095 } 096 case '\'' : { 097 sb.append("'"); 098 break; 099 } 100 case '\"' : { 101 sb.append("""); 102 break; 103 } 104 default : sb.append(c); 105 } 106 } 107 return sb.toString(); 108 } 109 110 /** 111 * Writes a file containing the SVG element. 112 * 113 * @param file the file ({@code null} not permitted). 114 * @param svgElement the SVG element ({@code null} not permitted). 115 * 116 * @throws IOException if there is an I/O problem. 117 * 118 * @since 1.2 119 */ 120 public static void writeToSVG(File file, String svgElement) 121 throws IOException { 122 writeToSVG(file, svgElement, false); 123 } 124 125 /** 126 * Writes a file containing the SVG element. 127 * 128 * @param file the file ({@code null} not permitted). 129 * @param svgElement the SVG element ({@code null} not permitted). 130 * @param zip compress the output. 131 * 132 * @throws IOException if there is an I/O problem. 133 * 134 * @since 3.0 135 */ 136 public static void writeToSVG(File file, String svgElement, boolean zip) 137 throws IOException { 138 BufferedWriter writer = null; 139 try { 140 OutputStream os = new FileOutputStream(file); 141 if (zip) { 142 os = new GZIPOutputStream(os); 143 } 144 OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8); 145 writer = new BufferedWriter(osw); 146 writer.write("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); 147 writer.write(svgElement + "\n"); 148 writer.flush(); 149 } finally { 150 try { 151 if (writer != null) { 152 writer.close(); 153 } 154 } catch (IOException ex) { 155 throw new RuntimeException(ex); 156 } 157 } 158 } 159 160 /** 161 * Writes an HTML file containing an SVG element. 162 * 163 * @param file the file. 164 * @param title the title. 165 * @param svgElement the SVG element. 166 * 167 * @throws IOException if there is an I/O problem. 168 */ 169 public static void writeToHTML(File file, String title, String svgElement) 170 throws IOException { 171 BufferedWriter writer = null; 172 try { 173 FileOutputStream fos = new FileOutputStream(file); 174 OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); 175 writer = new BufferedWriter(osw); 176 writer.write("<!DOCTYPE html>\n"); 177 writer.write("<html>\n"); 178 writer.write("<head>\n"); 179 writer.write("<title>" + title + "</title>\n"); 180 writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"); 181 writer.write("</head>\n"); 182 writer.write("<body>\n"); 183 writer.write(svgElement + "\n"); 184 writer.write("</body>\n"); 185 writer.write("</html>\n"); 186 writer.flush(); 187 } finally { 188 try { 189 if (writer != null) { 190 writer.close(); 191 } 192 } catch (IOException ex) { 193 Logger.getLogger(SVGUtils.class.getName()).log(Level.SEVERE, 194 null, ex); 195 } 196 } 197 } 198 199 /** 200 * Returns a string representing the specified double value. Internally 201 * this method is using the code from: https://github.com/ulfjack/ryu which 202 * is optimised for speed. 203 * 204 * @param d the value. 205 * 206 * @return A string representation of the double. 207 * 208 * @since 5.0 209 */ 210 public static String doubleToString(double d) { 211 return RyuDouble.doubleToString(d); 212 } 213 214 /** 215 * Returns a double-to-string function that limits the output to a 216 * specific number of decimal places (in the range 1 to 10). 217 * 218 * @param dp the decimal places (required in the range 1 to 10). 219 * 220 * @return The converter. 221 * 222 * @since 5.0 223 */ 224 public static DoubleFunction<String> createDoubleConverter(int dp) { 225 return new DoubleConverter(dp); 226 } 227 228}