API Review RT:17407 Canvas Node

Dr. Michael Paus mp at jugs.org
Thu Apr 26 08:42:54 PDT 2012

 From what I have read about the new Canvas node now, I have to
conclude that it will only be of very little use for me. I think
it would be very important to clarify the design goals first
before any decisions are made on the technical concept.

My original expectation was that the Canvas is a Node which
manages an image buffer (actually two of them for double
buffering) and provides me with an immediate mode graphics context
which would allow me to draw directly into this image buffer. My
expectation was also that I could do this drawing at any time
on a background thread so that I could keep long lasting renderings
away from the normal rendering thread. In addition to that I
expected that this graphics context would implement a general
purpose 2D drawing interface (or extend an abstract class) which
could later be used to implement graphics contexts for other output
types like SVG, PDF, etc.

I spent some of my spare time in the last couple of weeks to
examine whether JavaFX could be used for GIS, CAD or similar
applications which make heavy use of graphic primitives.
My conclusion so far is that this would currently
be very difficult if not impossible and I was hoping that the
new Canvas would help me here to improve the situation but apparently
it does not.

Let me explain how I got to this conclusion.

The first problem is drawing performance. When you have a complex
drawing, a critical operation is to pan your drawing or to zoom
in and out. The user expects this to be a smooth operation and
so I started to examine how many graphic primitives you could
have in your scene graph and still have an acceptable pan and zoom.
(This was partly inspired by the first JIRA entry below.)

The result is a bit frustrating because it turns out that JavaFX
is actually quite slow for practical scenarios. At first I tried
simple line shapes and on my laptop the limit seems to be at
around 50,000 lines. This looks quite good but then I tried to
put these lines into a Path object because in practice you do not
deal so often with simple unconnected lines. With the lines within
a Path the limit for an acceptable pan and zoom drops to around 500
lines, which is not very much. This number can already be exceed
by just implementing a fine background grid that way. One also
has to know that even simple polylines and polygons do suffer from
the same performance degradation because internally they are based
on a path object too. Only simple lines, circles and rectangles
are rendered in hardware. All other shapes are rendered in software
and are too slow for the affore mentioned type of application.
You also have to expect additional surprises. For example Rectangles
are normally rendered in hardware and are thus quite fast unless
you accidentally set the line join to Bevel. The performance then
drops tremendously.

The details and some explanations for all this can be found here:

The conclusion here is that it is currently not possible to get
an acceptable drawing performance for the non-trivial shape types
even if you know that you will never use any of the features that
hinder a hardware acceleration. There are no rendering hints or
something like that so that the programmer could make a choice.

To summarize this: Complex renderings just take too long and
prevent a smooth pan and zoom operation. The new Canvas also won't
be of any help here because, as I have learned, it also has to do
its rendering on the rendering thread and thus delays all other
rendering in the same way as the scene graph does. The only thing
you get is the buffering effect but that could in principle be
achieved already right now without the Canvas.

In order to achieve such a buffering, and thus allowing a smooth pan,
I put all my shapes in a group node and then activated the caching
of this group node. All the rendering of my shapes is now captured
in a bitmap and I get my smooth pan. In principle this works
nicely but I have not been able to solve the zooming problem in
the same way. It also does of course not solve the problem that
the initial rendering is done on the rendering thread. I hoped
that the Canvas would help here but apparently it doesn't.

Handling a zoom in the same way did not work because there seems
to be something wrong with the logic of the caching when you switch
between QUALITY and SPEED. The details can be found here:

There are a lot more conceptual issues which make the use
of JavaFX problematic for me at the moment. For example it is
difficult to handle the selection of many overlapping shapes.
Details can be found here:

Working with Transforms is also problematic because you
cannot perform any mathematical operations on them.
(Not yet reported.)

So coming back to the Canvas issue. I am still trying to understand
which problem the current Canvas proposal is actually supposed to solve.

- It does not provide a real immediate mode rendering into a bitmap.
- It does not prevent the creation of a potentially huge amount of
   objects because it first creates a render list internally.
- The render list is executed on the rendering thread and thus blocks it.
- The render list cannot be created on a separate thread.

Please forgive me if this posting was a bit long but I just had to
write off my frustration from my soul (as we say here).
You can now stone me if you like :-)


Dr. Michael Paus, Chairman of the Java User Group Stuttgart e.V. (JUGS).
For more information visit www.jugs.de.

More information about the openjfx-dev mailing list