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 WritableImage((int)Math.rint(renderScale*canvas.getWidth()), (int)Math.rint(renderScale*canvas.getHeight()));
        }
        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.

Michael



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


Reply via email to