On Wed, 19 Aug 2026 05:09:02 GMT, John Hendrikx <[email protected]> wrote:

>> We've still lost the information to decide whether 10.0000001 is a tiny, but 
>> intended offset that should round to 11, or whether it is noise and the 
>> result should round to 10.
>> 
>> But let's assume we make the ceil function a bit fuzzy, so that it tolerates 
>> arithmetic on snapped values where the final result is not snapped again. 
>> That doesn't make the snapping API a good idea, or even just remotely useful 
>> for custom controls, because even with the snap-the-result rule gone, there 
>> are still a lot of other ways in which developers will definitely get 
>> snapping wrong.
>> 
>> I think the only way how third-party developers can create custom layouts 
>> that actually work is to offer an API to compose them from well-tested 
>> primitives, like your virtual layout container proposal.
>
>> It is true that your idea improves perturbation stability of 
>> sloppily-snapped calculations, but I think that it doesn't improve the 
>> result if the snapping was done correctly to begin with (that is, discard 
>> any arithmetic excess if you know that your calculation was done on 
>> pixel-aligned values)
> 
> Yeah, but that does set a very high bar. Even a simple addition like `return 
> left + size + right` is wrong even when all values were snapped here. What 
> I'm suggesting is that with a slightly less "edgy" ceil function, you only 
> need one rule: 
> 
> - snap all input values before use
> 
> If we didn't have `ceil` anywhere, but all functions used rounding, then that 
> would have been sufficient. And that seems to have been the thought process 
> behind the implementation of almost all layout containers (they snap their 
> inputs, then calculate without further snapping).
> 
> However `snapSize`, which intent is to **snap a content-size to a size so all 
> of it is visible**, was implemented in a strict mathematical sense that is 
> sensitive to tiny floating point errors; in reality it was intended to ensure 
> all content pixels were visible; do we really need to ensure that an overflow 
> of 0.00000000000002 is "visible" ? That extra pixel allocated there will be 
> blank (even with anti-aliasing).
> 
> So I agree that `ceil` as implemented now is correct in the mathematical 
> sense, but that's not what we're trying to achieve. We're trying to achieve 
> correct snapping for content sizes, not ceiling.

It looks like my 2nd reply (sorry) cross with this one.

> We've still lost the information to decide whether 10.0000001 is a tiny, but 
> intended offset that should round to 11, or whether it is noise and the 
> result should round to 10.

The point I tried to make in the reply above was what exactly does a content 
size of `10.0000001` mean?  Is that 0.0000001 extra pixel going to be visible 
and relevant that it must be rendered?  

> But let's assume we make the ceil function a bit fuzzy, so that it tolerates 
> arithmetic on snapped values where the final result is not snapped again. 
> That doesn't make the snapping API a good idea, or even just remotely useful 
> for custom controls, because even with the snap-the-result rule gone, there 
> are still a lot of other ways in which developers will definitely get 
> snapping wrong.

I lost you at the point where you went to "That doesn't make the snapping API a 
good idea..." -- what API?

I'm not criticizing this documentation update; I think it's great. I am merely 
asking ourselves the question: are we going to let floating point artifacts and 
the current implementation of a mathematically accurate `ceil` function dictate 
how a large part of snapping must work?  As we're now about to formalize this 
in API docs.

The original intent of `snapSize` is clear: to snap widths/heights of content 
areas that users interact with, in such a way that no information is lost 
visually.  Now I contend that it was never the intention of this function to 
ensure a potential 0.0000001 pixel overflow (or since we're using doubles, 
currently even much worse, a 1e-14 overflow) **must** be displayed as otherwise 
important information is lost.

Rounding 1 millionth of a pixel doesn't lose information.

I'm not saying we change `ScaledMath` here (as that defines a `ceil` function 
which is correct as is).  I am saying `snapSize` should not be using 
`ScaledMath.ceil` but something more relevant to the task at hand, where 
fractional pixels, too tiny to be relevant for the goal of displaying 
"content", have no bearing on the outcome.

I mean if my control says its width must preferably be 10.0000001 (which it is 
only allowed to return if unsnapped), even if intended, it would still be 
invisible if the parent choses to render this as 10 pixels.

Now to potentially poke a hole in my own argument: this does mean that if 
`computeMinWidth` returns `10.000001`, I'm allowed to interpret that as 10; 
just like we now allow a value that strictly exceeds `10` by 1 ulp (even if 
`10` can be exactly represented) to be interpreted as `10`.  I'm merely 
suggesting to extend this value (and `ulp` is still incorrect for other 
reasons, see `Double.MAX_VALUE`) by something that is more in tune with what 
we're dealing with here, finite device pixels.

> I think the only way how third-party developers can create custom layouts 
> that actually work is to offer an API to compose them from well-tested 
> primitives, like your virtual layout container proposal.

Any control author still must implement the `compute` functions; and most of 
the well tested primitives that they may want to use are package private on 
`Region` (and to be honest, they better remain that way as their API is too 
poor to expose).

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/2260#discussion_r3811129017

Reply via email to