Canvas Content Shift

Michael Paus mp at
Fri Apr 14 14:36:43 UTC 2017

I think we can agree that this is kind of an expert feature but you 
definitely need such features
for any high-level interface if you want to achieve a good performance.

The root of the problems you have described is the same as the one you 
are already confronted
with today when you want to make a clear and crisp snapshot of a canvas. 
A simple snapshot on
a system with pixel scaling is blurry and totally unusable. In order to 
avoid this I use the code below.

     public static WritableImage renderScaleAwareCanvasSnapshot(Canvas 
canvas, double renderScale, WritableImage writableImage) {
         if (writableImage == null || 
(int)Math.rint(writableImage.getWidth()) != 
(int)Math.rint(renderScale*canvas.getWidth()) || 
(int)Math.rint(writableImage.getHeight()) != 
(int)Math.rint(renderScale*canvas.getHeight())) {
             writableImage = new 
         SnapshotParameters spa = new SnapshotParameters();
         spa.setTransform(Transform.scale(renderScale, renderScale));
         return canvas.snapshot(spa, writableImage);

For my Mac (Retina) I know that the renderScale is 2.0 but how do you 
find that out in the general case?
I am asking for such an API already for quite a while. Once you know the 
renderScale things become easy.
In principle you can do the canvas shift already right now by using the 
above code, although the performance will
of course be sub-optimal. That's the reason why we ask for a more 
specific API here so that ideally this
shift could be done completely on the graphics hardware.


Am 10.04.17 um 20:17 schrieb Jim Graham:
> Any suggestions on how to implement this when the size of pixels may 
> be an arbitrary non-integer number?
> Consider rendering on a 125% scaled Windows 10 screen.  If you want to 
> scroll by 2 pixels you would want to scroll by 1.6 coordinate units.  
> If you want to scroll by 2 coordinate units you are out of luck 
> because that would attempt to "scroll by 2.5 pixels" and there is no 
> good definition of that type of operation.
> We could add a pixel size parameter (note that it might be different 
> than the window or screen render scale because the Canvas cannot 
> re-render and so it chooses the scale of the deepest screen).  Then it 
> would be up to the developer to take this into account when 
> determining how far to scroll, but that is a bit more complicated than 
> what developers tend to be used to when they deal with scrolling.
> Note that the scrolling of JViewport is handled by our own code, not 
> developer code, so we can take these adjustments into account 
> ourselves internally and know if/when we can blit or if/when we need 
> to re-render...
>             ...jim
> On 4/10/17 1:32 AM, Dirk Lemmermann wrote:
>> HI there,
>> I was wondering if there is any chance that Java 10 could implement 
>> some sort of „content shifting“ for the Canvas API?
>> I would love to have this feature for supporting faster horizontal 
>> scrolling in my Gantt Chart framework FlexGanttFX. Currently when the 
>> user scrolls then the entire content of each canvas in each row of 
>> the chart will be redrawn. This could be optimized by only drawing 
>> the time range that has been moved into the „viewport“ and by 
>> shifting or copying the remaining time range graphics. E.g. the user 
>> currently looks at one week and scrolls one day to the right then the 
>> data / graphics of 6 days would stay the same and could just be 
>> reused. Only one day worth of data would need to be redrawn.
>> I think in Swing this is comparable with the BLIT_SCROLL_MODE of 
>> JViewport.
>> Dirk

More information about the openjfx-dev mailing list