Artikel Navigation

Canvas for Bck2Brwsr

Almost two weeks ago I met Jaroslav Tulach in Linz for our annual NetBeans Platform certified Training at the Johanes-Kepler-University in Linz. Every year we take some time to talk about projects and do some coding over a couple of beers, producing “Barcode” if you will. Last year we created a dynamic upload center for NetBeans Platform applications. This year Jarda showed me his new project Bck2Brwsr. The goal of the project is to bring Java back to the Browser. Java has lost a lot of ground in that area, and the advent of smartphones and tablets speeds up this trend, since it’s getting harder and harder to set up the environment for executing Java applications or applets.

In the meantime JavaScript is delivering on the WORA promise Java once started with. And while Java is great as a language especially for larger projects, for structuring and modularizing code in order to create maintainable projects, the platform has lost a lot of ground on the devices. Developers like the language, the superior IDE support as compared to JavaScript, the compile time checks, but for Browser based Projects, Java is no longer a choice as client technology.

The main idea of Bck2Brwsr is to change that and make it dead simple to execute Java Code in the Browser on any device. Since JavaScript is ubiquitous, it’s the obvious target language. GWT solves the problem by providing some APIs and a compiler that generates JavaScript. Bck2Brwsr is different in that it creates a JVM that is written in JavaScript and is capable of executing Java Bytecode directly. So when a Java runtime is available, the code could be executed by that, and benefit from the superior performance of the JVM. But if there’s no JVM, a minimal environment is automatically installed and runs the code in the Bck2Brwsr VM. And if you wonder how such a system will perform, I found Bck2Brwsr to be surprisingly fast already.

Another difference to GWT is, that there’s no standard API for widgets. The idea is, that you as a developer can very easily create your own APIs. For my current projects that would be excellent. I’ve created a GameEngine that is using JavaFX Canvas to render TileMaps and Sprites, and my plan was to create a JavaScript/ HTML5 Canvas version of that as well, so I can target any device. Over a couple of Austrian beers Jarda showed me how to implement such an API, and yesterday I found a little time to code so I gave it a try.

The final plan is to recreate the JavaFX Canvas API to render to HTML5 Canvas. But there are some differences, e.g. how the individual functions like arc and arcTo work. The bigger differences are additional features of JavaFX Canvas like the ability to use SVG paths. All of that should be no big problem, but require some work. So I decide to first implement a 1:1 Java version of the HTML5 Canvas API.

Time to head over to w3schools and have a look at Canvas. There are several subsections. The first one is ”Colors, Styles, and Shadows”. Here we have a couple of properties we can read or set on the GraphicsContect of the Canvas, like fillStyle, strokeStyle, etc.. So what we first need to do is create a representation of the Canvas Element and it’s GraphicsContext:

We will also need to register our Element with Bck2Brwsr’s PageProcessor. Now when the PageProcessor hits a Canvas Element on the Web page, it will create a Canvas Element for us. The @JavaScriptBody annotation can be used to directly generate the native JavaScript Code for us. In getContextImpl it will find the current Canvas Object and call a method on it to give us the GraphicsContext. We then create a Java Object Wrapper around that JavaScript Object:

So the getter/setter style for simple types is fairly simple to implement. It get’s slightly more complicated when dealing with Objects. HTML5 Canvas also allows us to set Gradients or Patterns as fills. These are JavaScript Objects, so we need some Wrappers to represent them in our Java Code, and we need to provide a reference to be used by the native code: