High performance text component
richard.bair at oracle.com
Thu Aug 2 20:14:13 PDT 2012
> 3) Canvas + fillText
> I tried this one, and it is pretty performant. On my laptop I can write
> 15k words on a big Canvas in only 30 msecs. Unfortunately Canvas can at
> the moment only use “Gray” as Font smoothing style, not “LCD”. But while
> this may come in future versions it has two other limitations:
> it does not deliver boundaries information when fillText is called. So I
> was forced, in my experiments, to first setText a Text component, get
> its layout bounds, and then calculate the coordinates for fillText.
> The second limitation is the most difficult one: a Canvas is limited to
> 8192x8192 pixels resolution. With a small font this would be good for
> about 700 LOC.
> So, the Canvas that I would need should allow 1mio x 1mio resolution.
> An alternative technique would be to have hundreds of smaller Canvas’,
> in Google Maps style, and put them together somehow.
With a Canvas approach. the way I would have approached it would have been to have a canvas the size of the viewport, and then simply use it as a place to draw all my text. The ScrollBar associated with it would be just sitting there, and I'd use its value as an indication of where to start drawing the text. For example, if I know that my text, all laid out, is going to be 10,000 pixels tall, then when the scroll bar value is at 5000 (I could just set the min at 0 and max at maxPixelSize that I computed to be 10k), then I know where in my data model I am to start drawing.
The problem with a Canvas that is too big is that it is stored as a single texture on the video card and the video card imposes limits.
> All those alternatives don’t look really usable for me.
> One thing that would be interesting is to have access to low-level
> functions of the JFX API. How does a javafx.scene.text.Text instance
> paint its LCD text on the screen?
> In principle what I would need is an infinite surface on which I can
> write and manipulate text with maximum speed, without adding nodes to
> the scenegraph. Modern video cards can run 3d games with way over 60 FPS
> and render complex scenarios with light. It should be possible to
> display text that is at least as fast (I know that JFX caps at 60 FPS,
> but that is fine). So when I have a massive 30 MB file with hundreds of
> thousands of lines of text, all colored and styled depending on the
> file type (Java code, Python code, etc), and this should scroll and
> resize very fluid.
> If the JFX team wanted to write the editor component for Eclipse 5,
> how would you approach that? Most likely not by using one of the three
> strategies that I layed out above.
That is true. Up to this point, we would have used Text nodes and virtualized / reused them, such that the same Text node can be reused for different text as the viewport is scrolled. Much like a ListView is virtualized or a TableView. This would keep the node count somewhat under control but would have been very complicated.
At the moment Felipe Heidrich is working on a plan for rich text for 3.0. He has the lower level underpinnings in place (the Prism text layout code is all primed for rich / complex text). I was going to meet with him early next week to do some discussions around API and how we want to surface this in the public API, so your timing is fantastic!
If you are happy to build on top of weekly builds of 3.0 then this could be the best solution. It works for us because it means we have a real world use case to drive development right off the bat which is quite beneficial. However if you have to ship something on a GA version of JavaFX, the best you have to work with is Canvas as described above or virtualized Text nodes.
More information about the openjfx-dev