0

I'm generating a website with JDenticon using this code (test.html):

<!DOCTYPE HTML>

<html>
    <head>
        <title>Test</title>
    </head>
    <body>
        <script src="https://cdn.jsdelivr.net/jdenticon/1.3.2/jdenticon.min.js" async></script>

        <svg width="200" height="200" data-jdenticon-hash="ff8adece0631821959f443c9d956fc39">
        Fallback text for browsers not supporting inline svg</svg>

    </body>
</html>

I want to get the image generated in this code to be accesible by a Java desktop application and want it to be saved on my PC. Is this possible and maybe also with changing the hascode (ff8adece0631821959f443c9d956fc39)

And whats the code for it?

Edit #1:

I've found something in the API of JDenticon that looks like this and is used for .NET Framework:

var engine = new Jurassic.ScriptEngine();
engine.ExecuteFile("<path to jdenticon.js>");
engine.SetGlobalValue("size", 200);
engine.SetGlobalValue("hash", "ff8adece0631821959f443c9d956fc39");

var svg = engine.Evaluate<string>("jdenticon.toSvg(hash, size)");
File.WriteAllText("testicon.svg", svg);

I wanted to do something like this in Java and found Java ScriptEngine (Tutorials: Oracle). But I don't know how to use it, right now my code looks like this:

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");

engine.put("size", 200);
engine.put("hash", "ff8adece0631821959f443c9d956fc39");

String svg = (String) engine.eval(new java.io.FileReader("C:/jdenticon.js"));

This obviously won't work because it does not call the jdenticon.toSvg(hash, size) method in the jdenticon.js file. So if someone has an idea on how to solve the problem with thisit would be very nice.

JetStream
  • 759
  • 1
  • 7
  • 26
  • 1
    Have you read the documentation of `JDenticon`? – amn Jul 04 '16 at 13:11
  • @amn Well, I think I have but haven't found a solution for Java. – JetStream Jul 04 '16 at 13:13
  • Java? JDenticon is a JavaScript library -- it works on the client side. That said, you *would* be able to render an icon on server side through Node.js, I think. You'd have to probably port JDenticon to Java source code, in order to get it to render icons as a Java application. Also, keep in mind that you don't have to use SVG for the icons -- you can use `canvas`, that is documented on JDenticon pages as well. – amn Jul 04 '16 at 13:15
  • @amn would it be easier to generate canvas? I don't care if it is a canvas or a svg, I just want to get the image through Java in the end. – JetStream Jul 04 '16 at 13:17
  • You'd need to explain me where does Java fit into your application of JDenticon. Otherwise it's hard to tell. Looks to me though that with your kind of application, `canvas` or `svg` does not matter much. Java can be an applet (deprecated, you can say) or it can be a servlet (server side) or a standalone desktop program. Java is many things. Can you update your question and elaborate on where and how Java fits in there? – amn Jul 04 '16 at 13:19
  • @amn specified it a bit – JetStream Jul 04 '16 at 13:25
  • I think I found a solution for you. And I think you will like it. – amn Jul 04 '16 at 14:03
  • Adding a Javascript runtime to your application just so you can run this tiny JS library is overkill. It would be simpler to port the code to Java. The code is very small. Unless you specifically want vector icons, it would probably be a lot easier to port the `Canvas` version of the generator, as the API to Java's `Graphics2D` class is quite similar. – Paul LeBeau Jul 04 '16 at 14:05
  • @amn I wonder what it is ^^ – JetStream Jul 04 '16 at 14:08
  • Well, Paul has a point -- porting the rather smallish JDenticon may be not that much of a job while using it from Java as-is is somewhat of an overkill. The code to use JDenticon as-is with Java as a script host, however, counts less than ten source code lines, and works fine here. I will draft an answer. – amn Jul 04 '16 at 14:22

1 Answers1

2

Your updated question including the interesting idea to just run the original code inside a JavaScript interpreter that is apparently built in into Java SE, made me pursue the approach further, resulting in the following code that I have tested to generate the SVG document text, which at least on my computer generates an expected SVG icon image.

import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.script.*;

public class JDenticonClient {
    public static void main(String args[]) throws FileNotFoundException, ScriptException {
        String svgText = new JDenticonClient().getSVGDocumentText("ff8adece0631821959f443c9d956fc39", 200);
        System.out.print(svgText);
    }
    public String getSVGDocumentText(String hash, int size) throws FileNotFoundException, ScriptException {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine scriptEngine = factory.getEngineByName("JavaScript");
        scriptEngine.eval(new FileReader("jdenticon.min.js"));
        return scriptEngine.eval("jdenticon.toSvg(\"" + hash + "\", \"" + size + "\")").toString();
    }
}

Even though we approached the same solution, you have to consider the following:

  1. The put method exposes additional script host objects to the scripts being evaluated. This is basically the entire point using script engines with a custom host that is not a web browser with a certain set of APIs or Node.js or anything like that. Basically, you can create your own APIs using put or simulate existing ones -- yes, even replicate the entire browser API set, making your application a scripting host compatible with a modern browser.
  2. I compose the evaluated string myself, but this is a technicality -- exposing native hash and size as String and int objects respectively, to the script using put would have worked as well, but then you have those as globals, which is not always a smart thing to do, given how these are natural one-shot parameters to the toSvg procedure.
  3. Even though you correctly included the JDenticon script evaluation, you may have not taken into account that by default, merely including (and running) the script simply calls jdenticon procedure which looks for canvas and svg elements inside a DOM tree, which in your case does not even exist. In fact, I am impressed the evaluation of the contents of the script file did not abort mid-way due to an exception where assumptions about DOM are made. But that's probably because the script is made to work with Node.js as well, which does not have DOM either.
  4. The code above can be optimized to not have to create a new factory and new script engine every time it needs to generate an SVG. I leave it all as an exercise.
  5. The getSVGDocumentText returns the entire generated SVG document as text. You'd have to add some logic if you want to e.g. save said text into an *.svg file.

P.S. Thanks for pointing me out in the direction of ScriptEngine. I didn't even know Java had one. Nice to know, never know.

amn
  • 6,917
  • 6
  • 48
  • 75
  • This solved the problem, thank you very much. I'm also trying to iplement the code in java and see if it makes a great difference in speed. – JetStream Jul 05 '16 at 06:42
  • It undoubtedly will -- there is no chance that the overhead of establishing and using a scripting host to run a rather tiny amount of what I assume is interpreted (as opposed to being compiled) code, is ever going to be less than just straightforward running Java code. I also advise you to make it generic -- no dependencies on a graphic context necessarily -- just use an interface that accepts vector graphic calls, so people can implement their own classes on top of it. Put it on Github, possibly merge with `JDenticon` repo itself. And... profit! ;-) – amn Jul 05 '16 at 11:38