package org.geogebra.desktop.gui; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import org.geogebra.common.awt.GGraphics2D; import org.geogebra.common.jre.gui.MyImageJre; import org.geogebra.common.util.Charsets; import org.geogebra.common.util.StringUtil; import org.geogebra.common.util.debug.Log; import org.geogebra.desktop.awt.GGraphics2DD; import com.kitfox.svg.SVGCache; import com.kitfox.svg.SVGDiagram; import com.kitfox.svg.SVGUniverse; public class MyImageD implements MyImageJre { private Image img; private SVGDiagram diagram; // SVG as XML private StringBuilder svg; public MyImageD(Image img) { this.img = img; } public MyImageD() { } /** * Load SVG from String * * @param svgStr * @param name */ public MyImageD(String svgStr, String name) { svg = new StringBuilder(svgStr.length()); svg.append(svgStr); InputStream stream = null; try { stream = new ByteArrayInputStream(svgStr.getBytes(Charsets.UTF_8)); } catch (UnsupportedEncodingException e1) { } SVGUniverse universe = SVGCache.getSVGUniverse(); URI uri; try { uri = universe.loadSVG(stream, name); diagram = universe.getDiagram(uri); } catch (IOException e) { e.printStackTrace(); } } public String getMD5() { if (img == null) { MessageDigest md; try { md = MessageDigest.getInstance("MD5"); md.update(svg.toString().getBytes(Charsets.UTF_8)); byte[] md5hash = md.digest(); return StringUtil.convertToHex(md5hash); } catch (RuntimeException e) { Log.error("MD5 Runtime Error"); return "svg" + UUID.randomUUID(); } catch (Exception e) { Log.error("MD5 Error"); return "svg" + UUID.randomUUID(); } } try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write((BufferedImage) img, "png", baos); byte[] fileData = baos.toByteArray(); MessageDigest md; md = MessageDigest.getInstance("MD5"); md.update(fileData, 0, fileData.length); byte[] md5hash = md.digest(); return StringUtil.convertToHex(md5hash); } catch (NoSuchAlgorithmException e) { // } catch (IOException e) { e.printStackTrace(); } Log.error("MD5 Error"); return "image" + UUID.randomUUID(); } public void load(File imageFile) throws IOException { if (StringUtil.toLowerCase(imageFile.getName()).endsWith(".svg")) { svg = new StringBuilder((int) imageFile.length()); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream(imageFile), Charsets.UTF_8)); for (String line = reader .readLine(); line != null; line = reader.readLine()) { // width or height missing, hack to add them in // needed for web try { if (line.startsWith("<svg")) { if (line.contains("viewBox=\"") && (!line.contains("height=\"") || !line.contains("width=\""))) { int index = line.indexOf('>'); String start = line.substring(0, index); String end = line.substring(index, line.length()); String pattern = "viewBox=\"([^\"]*)\""; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(line); if (m.find()) { Log.debug("Found value: " + m.group(1)); String[] values = m.group(1).split(" "); if (values.length == 4) { double xmin = Double .parseDouble(values[0]); double ymin = Double .parseDouble(values[1]); double xmax = Double .parseDouble(values[2]); double ymax = Double .parseDouble(values[3]); double width = Math.abs(xmax - xmin); double height = Math.abs(ymax - ymin); line = start + " width=\"" + width + "\" height=\"" + height + "\"" + end; Log.error( "patching SVG file to include height and width:\n" + line); // Log.debug("line = " + line); // Log.debug("start = " + start); // Log.debug("end = " + end); } } } } } catch (Exception e) { Log.error("problem parsing viewBox from SVG"); } svg.append(line); svg.append('\n'); } } finally { if (reader != null) { reader.close(); } } URL url = imageFile.toURI().toURL(); SVGUniverse universe = SVGCache.getSVGUniverse(); URI uri = universe.loadSVG(url); diagram = universe.getDiagram(uri); } else { img = ImageIO.read(imageFile); } } public Image getImage() { return img; } @Override public boolean hasNonNullImplementation() { return img != null; } @Override public boolean isSVG() { return diagram != null; } @Override public int getHeight() { if (img != null) { return img.getHeight(null); } if (diagram != null) { return (int) (diagram.getHeight() + 0.5); } return 1; } @Override public int getWidth() { if (img != null) { return img.getWidth(null); } if (diagram != null) { return (int) (diagram.getWidth() + 0.5); } return 1; } @Override public void drawSubimage(int startX, int startY, int imgWidth, int imgHeight, GGraphics2D g, int posX, int posY) { GGraphics2DD.getAwtGraphics(g).drawImage(((BufferedImage) img) .getSubimage(startX, startY, imgWidth, imgHeight), null, posX, posY); } @Override public GGraphics2D createGraphics() { return new GGraphics2DD((Graphics2D) img.getGraphics()); } public SVGDiagram getDiagram() { return diagram; } @Override public String getSVG() { return svg.toString(); } public void drawImage(Graphics2D g2, int x, int y, int width, int height) { if (img != null) { // bitmap g2.drawImage(img, x, y, width, height, null); } else { // SVG try { diagram.render(g2); } catch (Exception e) { Log.error("Drawing svg image failed"); } } } }