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