Thanks for looking at this Werner!

On 2/18/2015 2:13 AM, Werner Lehmann wrote:
Hi Jim,

As to the question of integer vs float
coordinates, there is a lot of snapToPixel stuff going on. And one of
the reasons is to get crisp pixel-aligned lines. Snapping to logical
coordinates could then snap to non-integer physical coordinates (if the
scaling factor is 125% or somesuch). Which may be ok if hidpi makes up
for it...

We have a number of "snap-to-pixel" cases within the FX code base for the very reason you state. I'm also wondering how often those calculations appear in application code?

Our intention is to (likely not in 8u60) provide a pixelScale attribute on some class (Scene? Stage? etc) so that snap-to-pixel can do its work. We may initially (and we must until we provide that API) only support integer scales (so at least retina gets its 2x and super-hi screens can get their 3x) since those would not "undo" the calculations of snap-to-pixel. To embrace non-integer scales in rendering we would need to expose that pixel scale and then the code that does pixel snapping would need to use:

    snappedCoord = Math.round(rawCoord * pixelScale) / pixelScale;

and all values would have to be floating point (the API tends to use doubles for numbers).

Unfortunately, when you said:

Some thoughts. Obviously it is less desirable to require every
> application to do their own scaling. I can't imagine that this
> would work on a larger basis.

That is the Windows model. They tell you how much you should scale your own content, and then they ask you to tell them how many actual pixels you want the window to be. You are then supposed to calculate a scaled version of your rendering, figure out how many pixels it is, and give that number to them. With FX, this could be as simple as providing a scaling transform above the root (this is actually how we render the scene) and letting everything else to its work. Nodes are supposed to embrace scaling from their ancestry so technically our nodes should already understand how to do this, but it may be a surprise when the root node doesn't see IDENTITY in its incoming "localToParent" transform. Would it?

If we went that way, then snap-to-pixel would work just fine as long as code that performed that calculation actually checked its full scene transform instead of just relying on "I know that my app code hasn't set any transforms in any of my parents so this node must be still at a 1:1 pixel scale".

In terms of what you said about "if HiDPI makes up for it"...

Actually retina sort of does this. The user can specify a number of resolutions in the preferences CP, but they always only use 2x scaling at the rendering level. The default is a scaling preference where the screen appears exactly 2 pixels per logical scaled coordinate and there is no pixel scaling. But, if you specify some other preference for screen content, then they use pixel stretching to get from the 2x scale that the application sees to the size on the screen requested by the user's preference. I have to look at their algorithm, but I've always been under the impression that it isn't simple linear interpolation.

Personally, I run my retina MBP screen, which has a native resolution of 2880x1800 and a "best for retina" scaling recommendation of "appears as if it is 1440x900" - but I run it in "appears like 1680x1050" mode so that I can fit more content on the screen. As a result, I am always getting some pixel stretching in reality, but I don't really notice it. This could be chalked up to "very Hi DPI screens cover a lot of pixel sins", or it could be "Apple chose an incredibly good pixel scaling filter". I need to look more into that. One thing to note is that this only works well on retina screens so it would probably not be a good technique for achieving the 125% scaling that many Windows screens request/recommend...

                        ...jim

Reply via email to