[OpenJDK 2D-Dev] [9] Review request for 8160124 SunGraphics2D.hitClip() can give wrong result for floating point scale
Sergey Bylokhov
Sergey.Bylokhov at oracle.com
Mon Jul 4 08:12:47 UTC 2016
On 01.07.16 2:49, Jim Graham wrote:
> How is it returning true? If the clip really is empty, then
> intersectsQuickCheck() should never return true. Or are you saying that
> an empty clip shape produces a non-empty composite clip region?
This code will test such situation:
BufferedImage bi = new
BufferedImage(10,10,BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bi.createGraphics();
graphics.scale(1.5, 1.5);
graphics.setClip(1, 1, 0, 0);
System.out.println("empty = " +
graphics.getClip().getBounds2D().isEmpty());
boolean hit = graphics.hitClip(1, 1, 1, 1);
System.out.println("hit = " + hit);
if "graphics.scale(1.5, 1.5);" will be removed then correct false will
be printed. In both cases the clip will be empty but hitCLip will return
different result in case of scaled SG2D.
>
> ...jim
>
> On 06/30/2016 10:02 AM, Sergey Bylokhov wrote:
>> It looks strange that the empty clip became "non-empty"(at least hitClip
>> reports this) when we apply transform to it, no? I guess that at the
>> beginning of hitClip() we should check that the clip.isEmpty(), and we
>> should return "false" in this case(I think this is not strictly related
>> to this bug)?
>>
>> On 24.06.16 1:14, Jim Graham wrote:
>>> Think of this method as asking:
>>>
>>> I don't want you to waste a lot of time, but tell me if it is silly for
>>> me to even consider rendering something with these bounds.
>>>
>>> And the answer is either "Oh, yeah, it is inconceivable that those
>>> bounds would be rendered", or "Not sure, maybe, just render it and
>>> see". There may be some cases where it knows "I know for sure that lots
>>> of stuff will render through the clip", but that is not where the
>>> divining line is here in terms of when the answer becomes true - it
>>> becomes true when there is a chance that it might render something.
>>>
>>> Arguably, the user-space comparison against the user-space clip that you
>>> added here can never be accurate even if you allow for "false
>>> positives". The clip is rasterized and whole pixels are chosen based on
>>> various criteria that affect clip rasterization. Thus, while the
>>> theoretical clip is at N.5, our rasterization choice has us render
>>> anything that hits pixel N, even if the contribution of the rendered
>>> primitive is only for the first half of N. That pixel might be rendered
>>> if anything hits any part of it, depending on what rendering operation
>>> is being done.
>>>
>>> So, your "fix" actually breaks the functionality because it is quite
>>> possible that something with a bounding box that stops before N.5 might
>>> affect pixel N and cause it to be rendered even though your new answer
>>> suggested that it wouldn't happen. Your code might actually cause a
>>> bug, not fix one.
>>>
>>> (There are also some potential theoretical failures related to how AA
>>> and STROKE_CONTROL might perturb our rendering, effects which are ignore
>>> by the current implementation of hitClip(), however I believe that all
>>> of those effects fit within the current implementation - it's just that
>>> I don't think anyone has ever proven this, or written an exhaustive test
>>> suite to verify that none of our rendering hints can perturb rendering
>>> by enough to create some surprises here...)
>>>
>>> ...jim
>>>
>>> On 6/23/16 3:00 PM, Jim Graham wrote:
>>>> Since "return true" would be a compliant implementation of
>>>> Graphics.hitClip(), this is not a bug...
>>>>
>>>> Read the documentation, it is allowed to use fast math that can return
>>>> true when technically the answer is false...
>>>>
>>>> ...jim
>>>>
>>>> On 6/23/16 5:04 AM, Alexandr Scherbatiy wrote:
>>>>>
>>>>> Hello,
>>>>>
>>>>> Could you review the fix:
>>>>> bug: https://bugs.openjdk.java.net/browse/JDK-8160124
>>>>> webrev: http://cr.openjdk.java.net/~alexsch/8160124/webrev.00
>>>>>
>>>>> Let's set the clip [x=5, y=5, width=5, height=5] to a graphics and
>>>>> call the hitClip() with the passed rectangle [x=0,
>>>>> y=0, width=5, height=5].
>>>>>
>>>>> The result is false for the graphics with scale 1 and true if the
>>>>> scale is floating point 1.5.
>>>>>
>>>>> This is because the transformed clip which has floating point
>>>>> bounds [7.5, 7.5, 7.5, 7.5] for the scale 1.5 has bounds
>>>>> with rounded down upper-left and rounded up lower-right corners [7,
>>>>> 7, 8, 8] which now intersects with the transformed
>>>>> rectangle [0, 0, 7.5, 7.5].
>>>>>
>>>>> The proposed fix adds additional check for the user clip and the
>>>>> user rectangle intersection if the intersection with
>>>>> the region clip passes.
>>>>>
>>>>> Thanks,
>>>>> Alexandr.
>>>>>
>>>>>
>>
>>
--
Best regards, Sergey.
More information about the 2d-dev
mailing list