Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-11-02 Thread Jim Graham
Tweaking might reduce the number of cases where the reverse transform 
makes a different edge condition decision than the forward transform, 
but it will never completely eliminate it and so the refine code (which 
exists because forward computations don't always match reverse 
computations) would still be needed.  Both could be part of the same fix 
- make the refinement more accurate and also consider if a better 
approximation of the transform would make the refinement actions more 
rare...


...jim

On 11/1/2016 8:30 AM, Sergey Bylokhov wrote:

But probably it is possible to tweak the transform? I mean that we can
apply the "round", then calculate the diff between resulted destination
and destination based on transform, and shift/rescale the transform so
it will map exactly the pixels from source edges to destination edges.

On 29.10.16 0:47, Jim Graham wrote:

I suppose that there could be a 4th bug about the fact that the
trimming/refining code in the native TransformHelper is based on an
inverse transform and subject to bit error, but it's not easy to figure
out how to refine it further.  Note that it could also cause us to omit
a row of pixels in some cases if the rounding went the other way.
Refining it further could be easier than the 2nd two solutions, but not
really noticeable if we just get do the more conservative calculations
on the bounds equations in the setup code...

...jim

On 10/28/16 2:33 PM, Jim Graham wrote:

Hi Alexandr,

That code is coming up with maximum extents for the operation, not the
exact edges that will be rendered.  It passes
them down to the native TransformHelper method which refines them
using the exact calculations it will use to render the
pixels.

Admittedly, the calculations you point out below in the DrawImage
pipeline would more accurately note that the
right/bottom edges fall on a .5 pixel location and shouldn't be
included, but I didn't want to make that decision using
one set of equations while the actual rendering uses different math
down below.

Note that if you had a rotation then there are lots of unused pixels
on each scanline which are computed and refined by
the native code.  Those calculations would also be performing the
"included/excluded" calculations using the actual
rendering equations rather than these higher level boundary equations
so even if we switched to "ceil(N - 0.5)"
calculations up here for the bounding box to cure the scaled drawImage
we'd still potentially have overshoot due to the
fixed point/floating point bit errors on those rotated edges.

With a general transform it would be difficult to detect the
occasional extra pixel being rendered due to bit errors,
but it is much easier with these scale-only transforms.

One change we could make would be to do the ceil(N-0.5) calculation in
the bounds setup code which would "fix" the scale
only case.

Another might be to fix the scale pipeline to handle arbitrary formats
- we could write a related "ScaleHelper" native
method that would do the same thing that TransformHelper does.
TransformHelper takes a transform loop that transforms
pixels to ARGB, and a separate Blit or MaskBlit that blends ARGB
pixels into the destination and it runs the first loop
into a temporary local buffer on the C call stack and the second loop
to blend the pixels into the dest.  A ScaleHelper
loop would do the same, but with a "Scale(XXX to ARGB)" loop for the
first half.

Finally, we could also add more ScaleBlit loops for more source/dest
pairs so these scales would happen more directly.
Unfortunately, many of the missing cases would require creating scale
loops that also do blending and the only macros we
currently have for direct src->dest scaling are opaque-to-opaque pixel
store operations.

The first solution is simpler and easier to add, the second one would
help with all scales that fall outside our loops.
The last solution would arguably provide the highest performance for
any source/dest case that we care about (and with
the advent of HiDPI we now care about a lot more cases).

I'd file 3 bugs:

- Scaled and transformed drawImage can overshoot with some scales (1.5)
- Add more ScaledBlit graphics primitive instances for common HiDPI
cases
- Create a general purpose Scale helper method along the lines of
TransformHelper

The first could be fixed soon with the proposed change you talk about
below...

...jim

On 10/28/16 6:40 AM, Alexandr Scherbatiy wrote:

On 10/11/2016 10:13 PM, Sergey Bylokhov wrote:

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no
matter how
much we predict which rules they may want because clips are
inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape
will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be
best to
have clipping remain unaffected by the biasing 

Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-11-01 Thread Sergey Bylokhov
But probably it is possible to tweak the transform? I mean that we can 
apply the "round", then calculate the diff between resulted destination 
and destination based on transform, and shift/rescale the transform so 
it will map exactly the pixels from source edges to destination edges.


On 29.10.16 0:47, Jim Graham wrote:

I suppose that there could be a 4th bug about the fact that the
trimming/refining code in the native TransformHelper is based on an
inverse transform and subject to bit error, but it's not easy to figure
out how to refine it further.  Note that it could also cause us to omit
a row of pixels in some cases if the rounding went the other way.
Refining it further could be easier than the 2nd two solutions, but not
really noticeable if we just get do the more conservative calculations
on the bounds equations in the setup code...

...jim

On 10/28/16 2:33 PM, Jim Graham wrote:

Hi Alexandr,

That code is coming up with maximum extents for the operation, not the
exact edges that will be rendered.  It passes
them down to the native TransformHelper method which refines them
using the exact calculations it will use to render the
pixels.

Admittedly, the calculations you point out below in the DrawImage
pipeline would more accurately note that the
right/bottom edges fall on a .5 pixel location and shouldn't be
included, but I didn't want to make that decision using
one set of equations while the actual rendering uses different math
down below.

Note that if you had a rotation then there are lots of unused pixels
on each scanline which are computed and refined by
the native code.  Those calculations would also be performing the
"included/excluded" calculations using the actual
rendering equations rather than these higher level boundary equations
so even if we switched to "ceil(N - 0.5)"
calculations up here for the bounding box to cure the scaled drawImage
we'd still potentially have overshoot due to the
fixed point/floating point bit errors on those rotated edges.

With a general transform it would be difficult to detect the
occasional extra pixel being rendered due to bit errors,
but it is much easier with these scale-only transforms.

One change we could make would be to do the ceil(N-0.5) calculation in
the bounds setup code which would "fix" the scale
only case.

Another might be to fix the scale pipeline to handle arbitrary formats
- we could write a related "ScaleHelper" native
method that would do the same thing that TransformHelper does.
TransformHelper takes a transform loop that transforms
pixels to ARGB, and a separate Blit or MaskBlit that blends ARGB
pixels into the destination and it runs the first loop
into a temporary local buffer on the C call stack and the second loop
to blend the pixels into the dest.  A ScaleHelper
loop would do the same, but with a "Scale(XXX to ARGB)" loop for the
first half.

Finally, we could also add more ScaleBlit loops for more source/dest
pairs so these scales would happen more directly.
Unfortunately, many of the missing cases would require creating scale
loops that also do blending and the only macros we
currently have for direct src->dest scaling are opaque-to-opaque pixel
store operations.

The first solution is simpler and easier to add, the second one would
help with all scales that fall outside our loops.
The last solution would arguably provide the highest performance for
any source/dest case that we care about (and with
the advent of HiDPI we now care about a lot more cases).

I'd file 3 bugs:

- Scaled and transformed drawImage can overshoot with some scales (1.5)
- Add more ScaledBlit graphics primitive instances for common HiDPI cases
- Create a general purpose Scale helper method along the lines of
TransformHelper

The first could be fixed soon with the proposed change you talk about
below...

...jim

On 10/28/16 6:40 AM, Alexandr Scherbatiy wrote:

On 10/11/2016 10:13 PM, Sergey Bylokhov wrote:

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no
matter how
much we predict which rules they may want because clips are inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape
will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be
best to
have clipping remain unaffected by the biasing of STROKE hints, but
part
of that is driven by the fact that I think it can be fixed with a
couple
of lines of code in SG2D/LoopPipe...


I guess a bottom line is that it is require an additional
investigation. I am not exactly sure, but my expectation is
that fillRect(x,y,w,h)/drawImage(x,y,w,h) + setClip(x,y,w,h) should
work in a similar way(covers the same pixels). And
the question should this behavior be exactly the same as
fill(RectShape) + setClip(RectShape) is unclear (I am not
sure is it a critical issue or not)
Right now I tried to fix overlapping, which produ

Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-28 Thread Jim Graham
I suppose that there could be a 4th bug about the fact that the trimming/refining code in the native TransformHelper is 
based on an inverse transform and subject to bit error, but it's not easy to figure out how to refine it further.  Note 
that it could also cause us to omit a row of pixels in some cases if the rounding went the other way.  Refining it 
further could be easier than the 2nd two solutions, but not really noticeable if we just get do the more conservative 
calculations on the bounds equations in the setup code...


...jim

On 10/28/16 2:33 PM, Jim Graham wrote:

Hi Alexandr,

That code is coming up with maximum extents for the operation, not the exact 
edges that will be rendered.  It passes
them down to the native TransformHelper method which refines them using the 
exact calculations it will use to render the
pixels.

Admittedly, the calculations you point out below in the DrawImage pipeline 
would more accurately note that the
right/bottom edges fall on a .5 pixel location and shouldn't be included, but I 
didn't want to make that decision using
one set of equations while the actual rendering uses different math down below.

Note that if you had a rotation then there are lots of unused pixels on each 
scanline which are computed and refined by
the native code.  Those calculations would also be performing the 
"included/excluded" calculations using the actual
rendering equations rather than these higher level boundary equations so even if we 
switched to "ceil(N - 0.5)"
calculations up here for the bounding box to cure the scaled drawImage we'd 
still potentially have overshoot due to the
fixed point/floating point bit errors on those rotated edges.

With a general transform it would be difficult to detect the occasional extra 
pixel being rendered due to bit errors,
but it is much easier with these scale-only transforms.

One change we could make would be to do the ceil(N-0.5) calculation in the bounds setup 
code which would "fix" the scale
only case.

Another might be to fix the scale pipeline to handle arbitrary formats - we could write a 
related "ScaleHelper" native
method that would do the same thing that TransformHelper does.  TransformHelper 
takes a transform loop that transforms
pixels to ARGB, and a separate Blit or MaskBlit that blends ARGB pixels into 
the destination and it runs the first loop
into a temporary local buffer on the C call stack and the second loop to blend 
the pixels into the dest.  A ScaleHelper
loop would do the same, but with a "Scale(XXX to ARGB)" loop for the first half.

Finally, we could also add more ScaleBlit loops for more source/dest pairs so 
these scales would happen more directly.
Unfortunately, many of the missing cases would require creating scale loops 
that also do blending and the only macros we
currently have for direct src->dest scaling are opaque-to-opaque pixel store 
operations.

The first solution is simpler and easier to add, the second one would help with 
all scales that fall outside our loops.
The last solution would arguably provide the highest performance for any 
source/dest case that we care about (and with
the advent of HiDPI we now care about a lot more cases).

I'd file 3 bugs:

- Scaled and transformed drawImage can overshoot with some scales (1.5)
- Add more ScaledBlit graphics primitive instances for common HiDPI cases
- Create a general purpose Scale helper method along the lines of 
TransformHelper

The first could be fixed soon with the proposed change you talk about below...

...jim

On 10/28/16 6:40 AM, Alexandr Scherbatiy wrote:

On 10/11/2016 10:13 PM, Sergey Bylokhov wrote:

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no matter how
much we predict which rules they may want because clips are inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be best to
have clipping remain unaffected by the biasing of STROKE hints, but part
of that is driven by the fact that I think it can be fixed with a couple
of lines of code in SG2D/LoopPipe...


I guess a bottom line is that it is require an additional investigation. I am 
not exactly sure, but my expectation is
that fillRect(x,y,w,h)/drawImage(x,y,w,h) + setClip(x,y,w,h) should work in a 
similar way(covers the same pixels). And
the question should this behavior be exactly the same as fill(RectShape) + 
setClip(RectShape) is unclear (I am not
sure is it a critical issue or not)
Right now I tried to fix overlapping, which produce visible artifacts and were 
considered as a bugs. The next issue
which I would like to fix is a overlapping of drawImage().

  I just created a small sample [1] which fills a rectangle (x, y, w, y), 
creates an image with size (w, h) and draws
the image into the area (x, y, w, h).

Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-28 Thread Jim Graham

Hi Alexandr,

That code is coming up with maximum extents for the operation, not the exact edges that will be rendered.  It passes 
them down to the native TransformHelper method which refines them using the exact calculations it will use to render the 
pixels.


Admittedly, the calculations you point out below in the DrawImage pipeline would more accurately note that the 
right/bottom edges fall on a .5 pixel location and shouldn't be included, but I didn't want to make that decision using 
one set of equations while the actual rendering uses different math down below.


Note that if you had a rotation then there are lots of unused pixels on each scanline which are computed and refined by 
the native code.  Those calculations would also be performing the "included/excluded" calculations using the actual 
rendering equations rather than these higher level boundary equations so even if we switched to "ceil(N - 0.5)" 
calculations up here for the bounding box to cure the scaled drawImage we'd still potentially have overshoot due to the 
fixed point/floating point bit errors on those rotated edges.


With a general transform it would be difficult to detect the occasional extra pixel being rendered due to bit errors, 
but it is much easier with these scale-only transforms.


One change we could make would be to do the ceil(N-0.5) calculation in the bounds setup code which would "fix" the scale 
only case.


Another might be to fix the scale pipeline to handle arbitrary formats - we could write a related "ScaleHelper" native 
method that would do the same thing that TransformHelper does.  TransformHelper takes a transform loop that transforms 
pixels to ARGB, and a separate Blit or MaskBlit that blends ARGB pixels into the destination and it runs the first loop 
into a temporary local buffer on the C call stack and the second loop to blend the pixels into the dest.  A ScaleHelper 
loop would do the same, but with a "Scale(XXX to ARGB)" loop for the first half.


Finally, we could also add more ScaleBlit loops for more source/dest pairs so these scales would happen more directly. 
Unfortunately, many of the missing cases would require creating scale loops that also do blending and the only macros we 
currently have for direct src->dest scaling are opaque-to-opaque pixel store operations.


The first solution is simpler and easier to add, the second one would help with all scales that fall outside our loops. 
The last solution would arguably provide the highest performance for any source/dest case that we care about (and with 
the advent of HiDPI we now care about a lot more cases).


I'd file 3 bugs:

- Scaled and transformed drawImage can overshoot with some scales (1.5)
- Add more ScaledBlit graphics primitive instances for common HiDPI cases
- Create a general purpose Scale helper method along the lines of 
TransformHelper

The first could be fixed soon with the proposed change you talk about below...

...jim

On 10/28/16 6:40 AM, Alexandr Scherbatiy wrote:

On 10/11/2016 10:13 PM, Sergey Bylokhov wrote:

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no matter how
much we predict which rules they may want because clips are inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be best to
have clipping remain unaffected by the biasing of STROKE hints, but part
of that is driven by the fact that I think it can be fixed with a couple
of lines of code in SG2D/LoopPipe...


I guess a bottom line is that it is require an additional investigation. I am 
not exactly sure, but my expectation is
that fillRect(x,y,w,h)/drawImage(x,y,w,h) + setClip(x,y,w,h) should work in a 
similar way(covers the same pixels). And
the question should this behavior be exactly the same as fill(RectShape) + 
setClip(RectShape) is unclear (I am not
sure is it a critical issue or not)
Right now I tried to fix overlapping, which produce visible artifacts and were 
considered as a bugs. The next issue
which I would like to fix is a overlapping of drawImage().

  I just created a small sample [1] which fills a rectangle (x, y, w, y), 
creates an image with size (w, h) and draws
the image into the area (x, y, w, h).
  With the floating point scale like 1.5 the image does not exactly fits the 
area filled by the rectangle (see image [2]
generated by the code [1]).

 This is because the Graphics.drawImage(...) calls DrawImage.renderImageXform() 
which uses floor and ceil methods for
the region corner rounding:
final int dx1 = Math.max((int) Math.floor(ddx1), clip.getLoX());
final int dy1 = Math.max((int) Math.floor(ddy1), clip.getLoY());
final int dx2 = Math.min((int) Math.ceil(ddx2), clip.getHiX());
final int dy2 = Math.min((int) Math.ceil(ddy2), clip.getHiY());


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-28 Thread Alexandr Scherbatiy

On 10/11/2016 10:13 PM, Sergey Bylokhov wrote:

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no matter how
much we predict which rules they may want because clips are inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be best to
have clipping remain unaffected by the biasing of STROKE hints, but part
of that is driven by the fact that I think it can be fixed with a couple
of lines of code in SG2D/LoopPipe...


I guess a bottom line is that it is require an additional 
investigation. I am not exactly sure, but my expectation is that 
fillRect(x,y,w,h)/drawImage(x,y,w,h) + setClip(x,y,w,h) should work in 
a similar way(covers the same pixels). And the question should this 
behavior be exactly the same as fill(RectShape) + setClip(RectShape) 
is unclear (I am not sure is it a critical issue or not)
Right now I tried to fix overlapping, which produce visible artifacts 
and were considered as a bugs. The next issue which I would like to 
fix is a overlapping of drawImage().
  I just created a small sample [1] which fills a rectangle (x, y, w, 
y), creates an image with size (w, h) and draws the image into the area 
(x, y, w, h).
  With the floating point scale like 1.5 the image does not exactly 
fits the area filled by the rectangle (see image [2] generated by the 
code [1]).


 This is because the Graphics.drawImage(...) calls 
DrawImage.renderImageXform() which uses floor and ceil methods for the 
region corner rounding:

final int dx1 = Math.max((int) Math.floor(ddx1), clip.getLoX());
final int dy1 = Math.max((int) Math.floor(ddy1), clip.getLoY());
final int dx2 = Math.min((int) Math.ceil(ddx2), clip.getHiX());
final int dy2 = Math.min((int) Math.ceil(ddy2), clip.getHiY());

But the Graphics.fillRect() falls down to the code which just cast the 
transformed coordinates to int.


Why the floor/ceil methods are used for the image region rounding?
Is it possible to change this to fit the rule for the filled rectangles 
rounding?


[1] http://cr.openjdk.java.net/~alexsch/fpapi/code/FillRectAndImageTest.java
[2] http://cr.openjdk.java.net/~alexsch/fpapi/screenshots/rect-and-image.png

Thanks,
Alexandr.







Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-12 Thread Jim Graham

On 10/11/16 12:49 PM, Jim Graham wrote:

Right now I tried to fix overlapping, which produce visible artifacts and were 
considered as a bugs. The next issue
which I would like to fix is a overlapping of drawImage().


Yes, that bears investigation...


I looked into it and the issue is basically floating point bit error.

Basically, in the test program we don't use a ScaledBlit because we don't have one defined for the combination of 
(IntArgb, SrcOver, IntArgb), since our ScaledBlit implementations are all for opaque images.  The loop macros can't even 
create a non-opaque ScaledBlit without a bit of work.


So, we end up in TransformHelper where we perform the blit by doing an inverse transform on the graphics transform and 
then use that to map back from destination pixels to the source pixels.


The issue here is that with a scale of 1.5, the forward transform is a nice IEEE-floating-point spec compatible bit 
pattern, but inverting it gives a scale of 2/3s which doesn't have an exact IEEE representation.  The result is that it 
marches through the image and the very last edge of that image maps to 10.5 which is an exact center of the pixel.  If 
the math were perfect then we'd back-transform that coordinate into the source image and get 7.0 and that would be "past 
the right edge of the image" and we'd bail at that point.  But, we back-transform it and get 6.9 and we think "OK, 
this pixel just squeaks by and gets one last sample of the image before we fall off the edge of the image".


But, this should not happen with 1:1 image copies.  And it shouldn't happen when we have a ScaledBlit function since 
that uses more exact math without inverting the scale, but I haven't written a test case to verify that.  And, it 
shouldn't happen with integer scales and scales where we don't have a situation of an image mapping to exactly 
(pixel+0.5).  But, I don't think we can improve the pixel accuracy of our inverse transforms to handle this exact case 
without a lot of work...


...jim


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Jim Graham

That looks good.  +1

...jim

On 10/11/16 4:32 PM, Sergey Bylokhov wrote:

On 11.10.16 23:12, Jim Graham wrote:

Also, is it worth having a protective test for Rectangle in the
intersect(Rectangle2D) method to avoid all of the double math when the
rectangle was already an integer one?


Yes, this code can be moved from SunGraphics2D:
http://cr.openjdk.java.net/~serb/8167310/webrev.05
+ isNaN checks were added



...jim

On 10/10/16 4:37 PM, Sergey Bylokhov wrote:

On 10.10.16 23:42, Jim Graham wrote:

Can we also not use MAX_INT for the drawImage test case?  Either have
the drawImage follow the clip around or choose an appropriate non-limit
size to cover the worst case scale with some margin for error...


Something like this?
http://cr.openjdk.java.net/~serb/8167310/webrev.04



On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01.
This also fixed the difference between clips(Shape vs
Rectangle).
 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix
if we set the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well?
Currently if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the
actual result in destination depends on what image was
painted first).
 - Should the clip be affected by the stroke(if it was set by the
shape)? Right now if the clip was set by the shape it
will produce different result than if it was set via rectangle.

On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path
and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same
mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.













Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Sergey Bylokhov

On 11.10.16 23:12, Jim Graham wrote:

Also, is it worth having a protective test for Rectangle in the
intersect(Rectangle2D) method to avoid all of the double math when the
rectangle was already an integer one?


Yes, this code can be moved from SunGraphics2D:
http://cr.openjdk.java.net/~serb/8167310/webrev.05
+ isNaN checks were added



...jim

On 10/10/16 4:37 PM, Sergey Bylokhov wrote:

On 10.10.16 23:42, Jim Graham wrote:

Can we also not use MAX_INT for the drawImage test case?  Either have
the drawImage follow the clip around or choose an appropriate non-limit
size to cover the worst case scale with some margin for error...


Something like this?
http://cr.openjdk.java.net/~serb/8167310/webrev.04



On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01.
This also fixed the difference between clips(Shape vs
Rectangle).
 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix
if we set the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well?
Currently if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the
actual result in destination depends on what image was
painted first).
 - Should the clip be affected by the stroke(if it was set by the
shape)? Right now if the clip was set by the shape it
will produce different result than if it was set via rectangle.

On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path
and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same
mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.











--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Jim Graham
Also, is it worth having a protective test for Rectangle in the intersect(Rectangle2D) method to avoid all of the double 
math when the rectangle was already an integer one?


...jim

On 10/10/16 4:37 PM, Sergey Bylokhov wrote:

On 10.10.16 23:42, Jim Graham wrote:

Can we also not use MAX_INT for the drawImage test case?  Either have
the drawImage follow the clip around or choose an appropriate non-limit
size to cover the worst case scale with some margin for error...


Something like this?
http://cr.openjdk.java.net/~serb/8167310/webrev.04



On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01.
This also fixed the difference between clips(Shape vs
Rectangle).
 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix
if we set the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well?
Currently if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the
actual result in destination depends on what image was
painted first).
 - Should the clip be affected by the stroke(if it was set by the
shape)? Right now if the clip was set by the shape it
will produce different result than if it was set via rectangle.

On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same
mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.










Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Jim Graham
One last thing.  In the clipRound() method you mention that NaN evaluates to 0.  I assume that is just an observation 
that we'd end up in the "(int) ceil()" case and the cast returns a 0.


In the case of a path we omit NaN coordinates, which means skipping segments in a path until they become sane again. 
That would likely turn a rectangle into a triangle if it happened in a shape, but in a Rectangle object the NaN ends up 
affecting more than one corner (minX is the coordinate of 2 corners, maxX is the coordinate for 2 corners, same for Y) 
and it degenerates further into an empty shape in all cases.  For example:


(x, y, w, h)
10, 10, NaN, 20
path is 10,10 => NaN,10 => NaN,30 => 10,30
=> 2 points eliminated
=> devolves to a vertical line
=> no pixels included

10, 10, 20, NaN
path is 10,10 => 30,10 => 30,NaN => 10,NaN
=> 2 points, devolves

NaN, 10, 20, 20
path is NaN,10 => NaN,10 => NaN,30 => NaN,30
=> no points left
=> completely degenerate

10, NaN, 20, 20
path is 10,NaN => 30,NaN => 30,NaN => 10,NaN
=> no points, degenerate

In the case of NaN in X and Y, the clipRound() method would end up returning 0 for both min and max of X or Y which 
would hopefully produce an empty region when we do the intersection.


In the case of NaN as a W or H, clipRound() would only produce a 0 for maxX or maxY, but the min would still be computed 
correctly.  I guess this could technically be considered an empty shape in practice since we tend to use Regions to only 
encompass pixels in a non-negative space, so it is fine in practice, but if we ever use translated Regions for some sort 
of use (what about shaped components which might use Region?) then 0 for maxX or maxY might be paired with a negative 
value for minX or minY and end up with a non-empty Region in the negative coordinates (and potentially translated later 
to positive coordinates and encompass some pixels on a destination drawable).


All of those would (should?) return a completely empty region if we rasterized the shape, so we should set an empty clip 
if we get a NaN in any coordinate...


...jim

On 10/10/16 4:37 PM, Sergey Bylokhov wrote:

On 10.10.16 23:42, Jim Graham wrote:

Can we also not use MAX_INT for the drawImage test case?  Either have
the drawImage follow the clip around or choose an appropriate non-limit
size to cover the worst case scale with some margin for error...


Something like this?
http://cr.openjdk.java.net/~serb/8167310/webrev.04



On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01.
This also fixed the difference between clips(Shape vs
Rectangle).
 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix
if we set the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well?
Currently if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the
actual result in destination depends on what image was
painted first).
 - Should the clip be affected by the stroke(if it was set by the
shape)? Right now if the clip was set by the shape it
will produce different result than if it was set via rectangle.

On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same
mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.










Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Jim Graham


On 10/11/16 12:13 PM, Sergey Bylokhov wrote:

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no matter how
much we predict which rules they may want because clips are inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be best to
have clipping remain unaffected by the biasing of STROKE hints, but part
of that is driven by the fact that I think it can be fixed with a couple
of lines of code in SG2D/LoopPipe...


I guess a bottom line is that it is require an additional investigation. I am 
not exactly sure, but my expectation is
that fillRect(x,y,w,h)/drawImage(x,y,w,h) + setClip(x,y,w,h) should work in a 
similar way(covers the same pixels). And
the question should this behavior be exactly the same as fill(RectShape) + 
setClip(RectShape) is unclear (I am not sure
is it a critical issue or not)


In STROKE_PURE, setClip/fillRect/drawImage(x,y,w,h) should all hit the same pixels.  I think we currently have a bug 
with drawImage() that needs to be investigated further, though.  The fact that it overlaps with itself is problematic 
and likely an indication that it won't match fillRect() either.


Under STROKE_NORMALIZE, fillRect() and fill(Rect) are affected due to their relationship to drawRect()/fill(Rect).  It's 
not clear if it should be identical to clipRect() and clip(Rect), though as I don't know where we'd have developers 
relying on that.  In particular, damage repair would usually involve clip(dmgxywh) followed by fill(compxywh) and so 
they wouldn't necessarily need to match.  drawImage() brings up additional questions.


For now I think we can ignore this issue for this fix, but I still have a question on the fix which I'll ask in response 
to webrev.04.  We should file the "clipRect() vs clip(RectShape)" bug for follow-on work.



Right now I tried to fix overlapping, which produce visible artifacts and were 
considered as a bugs. The next issue
which I would like to fix is a overlapping of drawImage().


Yes, that bears investigation...

...jim



Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Sergey Bylokhov

On 11.10.16 21:54, Jim Graham wrote:

Additionally, for AA rendering, there is no such thing as
"setClip(someShape)" and "fill(sameShape)" being identical no matter how
much we predict which rules they may want because clips are inherently
non-AA and so the fuzzy pixels along the boundary of an AA shape will be
randomly clipped or included.

When all is said and done I feel (not very strongly) it would be best to
have clipping remain unaffected by the biasing of STROKE hints, but part
of that is driven by the fact that I think it can be fixed with a couple
of lines of code in SG2D/LoopPipe...


I guess a bottom line is that it is require an additional investigation. 
I am not exactly sure, but my expectation is that 
fillRect(x,y,w,h)/drawImage(x,y,w,h) + setClip(x,y,w,h) should work in a 
similar way(covers the same pixels). And the question should this 
behavior be exactly the same as fill(RectShape) + setClip(RectShape) is 
unclear (I am not sure is it a critical issue or not)
Right now I tried to fix overlapping, which produce visible artifacts 
and were considered as a bugs. The next issue which I would like to fix 
is a overlapping of drawImage().



--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Jim Graham



On 10/10/16 3:23 PM, Phil Race wrote:

That last sentence sounds like the right answer in principle but I don't know 
if we'll be unpleasantly surprised
by some  consequence of "... that setClip(Shape) and fill(Shape) might disagree 
.."

-phil.


As I was thinking more about this last night we have additional issues to 
consider.

Our rasterization rules bend a bit under STROKE_CONTROL and they do so differently for AA and non-AA.  Really 
STROKE_CONTROL was a bandaid for the fact that the suddenly specific rasterization rules we created with the 2D API 
didn't necessarily match what developers had been used to and so we'd need some time for them to adjust.  In particular, 
a common misunderstanding is that "drawLine(X,0,X,h)" would fill in all of the pixels in the X column, but in AA this 
would not work right as it would fill half of (coverage-wise 50% blending) the pixels to the right of X and half of the 
pixels to the left of X and look fuzzy.  Similarly, exact insideness rules meant that even with non-AA and a line width 
of 1, technically the outline for that "line" would suggest that the pixels in the column to the left of X would be drawn.


In retrospect, we should have been advising developers to wean themselves off of STROKE_NORMALIZE adjustments from the 
release of Java 2, but we dropped that ball.  :(  To be fair, though, these issues had been common in dealing with other 
rendering systems, like Postscript - but how many developers have ever written Postscript code themselves?


Now with JavaFX we no longer have STROKE_CONTROL at all and we honor the strict rasterization rules that Java2D should 
be honoring under STROKE_PURE and so developers must learn how to be more selective in how the render things from their 
first exposure to FX.  So, the ins and outs of dealing with the specific rasterization rules (things like where to 
center lines, and manually snapping to pixels because "ints" don't do it pseudo-automatically for you) should be 
becoming part of the developer experience with FX.  I'm not sure how much that will help in Swing/AWT when Java2D has 
had NORMALIZE rules as default for a couple of decades.


The rules for STROKE_NORMALIZE were created so that fills and strokes would match and be non-surprising for both AA and 
non-AA modes, but the rules needed were different for the 2 modes.  Having different rules was fine because nobody would 
expect someone to draw a shape with non-AA and then fill it with AA or vice versa.  It is very much expected that the AA 
hint would stay the same for both a fill and a draw of a shape.


But, will the AA hint (or even the STROKE hint) stay the same for both the setting of a clip shape and the rendering of 
items in it?  How often is clip(someShape) followed by draw(sameShape) or fill(sameShape)?  Would a developer believe 
that the hints would affect the clip and so they would do the clip adjustment first and then set all of their "rendering 
hints"?  (Note that these are called "RenderingHints", though if I were to come up with a clip-specific hint I would 
have no qualms adding it to the bag of hints in the RH class...)


Additionally, for AA rendering, there is no such thing as "setClip(someShape)" and "fill(sameShape)" being identical no 
matter how much we predict which rules they may want because clips are inherently non-AA and so the fuzzy pixels along 
the boundary of an AA shape will be randomly clipped or included.


When all is said and done I feel (not very strongly) it would be best to have clipping remain unaffected by the biasing 
of STROKE hints, but part of that is driven by the fact that I think it can be fixed with a couple of lines of code in 
SG2D/LoopPipe...


...jim


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-11 Thread Jim Graham



On 10/10/16 3:53 PM, Sergey Bylokhov wrote:

On 11.10.16 1:23, Phil Race wrote:

Yes, I think adjacent drawImage requests should not overlap.  We
should look into this separately.


So previously, overlapping of the clip bounds ensured adjacent images
were not drawn
over-lapped .. but with this fix they might be ?


The fix change only behavior of the rectangle clip. So using the setClip we can 
prevent overlaping of the images. But i
think that even without clip such images should not overlap.


I'm pretty sure that setClip(x,y,w,h) would ensure adjacency (no overlaps and no gaps) with another call to itself with 
adjacent parameters.


And setClip(RectShape) would also ensure proper adjacency with itself.

But, I think we had cases before this fix where setClip(x,y,w,h) could violate proper adjacency with setClip(RectShape). 
 This fix addresses most of that, particularly it works if we have STROKE_PURE.  I believe that it still has issues 
with STROKE_NORMALIZE, though, because one of them honors it and the other doesn't.  So, we need to have them both honor 
the STROKE_CONTROL in the same way.



On the other hand, we normalize differently for AA and non-AA. Calling
getFillSSI() on LoopPipe basically performs normalization only for
non-AA fills.  Arguably, though, clipping produces non-AA results in
that it chooses whole pixels to include or exclude. This might mean
that it should never follow AA normalization.


That last sentence sounds like the right answer in principle but I don't
know if we'll be unpleasantly surprised
by some  consequence of "... that setClip(Shape) and fill(Shape) might
disagree .."


I just tested fillRect vs fill(RectShape), and both work differently in some 
cases as well-=((.
So we have a few similar methods which works differently(even if 
VALUE_STROKE_PURE is set), which became visible on
fractional(1.5) scales
 - setClip(Rectangle)
 - setClip(Shape)
 - fillRect(Rectangle)
 - fill(Shape)
 - DrawImage(Rectangle)


I'd like to see which cases cause differences.  The main one that I can see by a brief examination of the code is the 
case of non-integer translations (but no scale).


I think we end up using the simplified FillRect primitives in the case of a non-integer translate, and that can cause a 
difference in effect.  We could fix SurfaceData's validation to not use the primitive pipeline unless the translation is 
integer, but that could cost performance for that case.  I'm not sure how often a non-integer translation with no other 
transform elements (i.e. scale) occurs, though.  We could teach the FillRect primitive (or its caller) to adjust for the 
STROKE_CONTROL more properly in the case of a non-integer translation, but I'm not sure how often that will come into 
play and benefit us.  Also, this might be fixable in the code that comes up with sg2d.transXY, which probably doesn't 
take STROKE hint into account...


...jim


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Sergey Bylokhov

On 10.10.16 23:42, Jim Graham wrote:

Can we also not use MAX_INT for the drawImage test case?  Either have
the drawImage follow the clip around or choose an appropriate non-limit
size to cover the worst case scale with some margin for error...


Something like this?
http://cr.openjdk.java.net/~serb/8167310/webrev.04



On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01.
This also fixed the difference between clips(Shape vs
Rectangle).
 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix
if we set the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well?
Currently if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the
actual result in destination depends on what image was
painted first).
 - Should the clip be affected by the stroke(if it was set by the
shape)? Right now if the clip was set by the shape it
will produce different result than if it was set via rectangle.

On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same
mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.








--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Sergey Bylokhov

On 11.10.16 1:23, Phil Race wrote:

Yes, I think adjacent drawImage requests should not overlap.  We
should look into this separately.


So previously, overlapping of the clip bounds ensured adjacent images
were not drawn
over-lapped .. but with this fix they might be ?


The fix change only behavior of the rectangle clip. So using the setClip 
we can prevent overlaping of the images. But i think that even without 
clip such images should not overlap.



On the other hand, we normalize differently for AA and non-AA. Calling
getFillSSI() on LoopPipe basically performs normalization only for
non-AA fills.  Arguably, though, clipping produces non-AA results in
that it chooses whole pixels to include or exclude. This might mean
that it should never follow AA normalization.


That last sentence sounds like the right answer in principle but I don't
know if we'll be unpleasantly surprised
by some  consequence of "... that setClip(Shape) and fill(Shape) might
disagree .."


I just tested fillRect vs fill(RectShape), and both work differently in 
some cases as well-=((.
So we have a few similar methods which works differently(even if 
VALUE_STROKE_PURE is set), which became visible on fractional(1.5) 
scales

 - setClip(Rectangle)
 - setClip(Shape)
 - fillRect(Rectangle)
 - fill(Shape)
 - DrawImage(Rectangle)



--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Phil Race



On 10/10/2016 01:34 PM, Jim Graham wrote:
[CC'ing Phil in case he has some suggestions for how the API should 
work...]


Responding just to additional questions in this email...

On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix 
if we set the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well? 
Currently if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the 
actual result in destination depends on what image was

painted first).


Yes, I think adjacent drawImage requests should not overlap.  We 
should look into this separately.


So previously, overlapping of the clip bounds ensured adjacent images 
were not drawn

over-lapped .. but with this fix they might be ?




 - Should the clip be affected by the stroke(if it was set by the 
shape)? Right now if the clip was set by the shape it

will produce different result than if it was set via rectangle.


I think we could have the clip never be affected by STROKE_NORMALIZE.  
That might make sense because the NORMALIZE code is meant to deal with 
aesthetic issues, not rendering math issues.  We'd have to add a 
getClipSSI() method that hard-codes the "adjust" boolean to "false" to 
do that, but that is an easy fix.


The question is then that would meant that setClip(Shape) and 
fill(Shape) might disagree, though.  This would argue that we should 
have it affected by the normalization.  This is also a fairly easy 
fix, you could have LoopPipe have a method that would return the 
appropriate Rectangle representing which pixels are covered for a 
given Rectangle2D depending on the normalize parameters.


On the other hand, we normalize differently for AA and non-AA. Calling 
getFillSSI() on LoopPipe basically performs normalization only for 
non-AA fills.  Arguably, though, clipping produces non-AA results in 
that it chooses whole pixels to include or exclude. This might mean 
that it should never follow AA normalization. 


That last sentence sounds like the right answer in principle but I don't 
know if we'll be unpleasantly surprised
by some  consequence of "... that setClip(Shape) and fill(Shape) might 
disagree .."


-phil.

But, it also points out the silliness of normalizing to match the 
results of fill when it can never do that for AA mode.  (Potentially 
we could add an AA-clip mode, but the implementation of that would 
require capturing every rendering operation to an intermediate buffer 
and then pixel-filtering it through a mask created by AA-filling the 
clip shape - we do that in FX, but it would require major surgery to 
add that to the SG2D pipeline so I don't think we would ever consider 
that at this stage.)


Any of those solutions are fairly easy to fix (except adding an AA 
clipping mode), but the question is which is more useful and/or 
surprises the developers the least.


So we have the current case:

setClip(integers or int-Rectangle) => pure coverage
setClip(other shape) => non-AA normalized coverage

If we decide that clip should normalize always to non-AA parameters 
because it is an intrinsically non-AA type of operation then we have 
to fix the setClip(integer rectangle) code which isn't hard.


If we decide that clip should normalize to the current AA parameters 
then it's basically the same, but we need to find a way to query the 
right objects to perform the AA according to their chosen bias.  
LoopPipe/ShapeSpanIterator appear to own non-AA normalization and I 
think AA normalization is hidden behind the TileGenerator API 
somewhere that Ductus/Pisces/Marlin all implement.


If we decide that clip should not normalize then we only have to fix 
setClip(other shape) and it's just a question of hard-coding the 
adjust boolean in the call to instantiate the ShapeSpanIterator.


Phil?

...jim




Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Jim Graham
Can we also not use MAX_INT for the drawImage test case?  Either have the drawImage follow the clip around or choose an 
appropriate non-limit size to cover the worst case scale with some margin for error...


...jim

On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01. This also 
fixed the difference between clips(Shape vs
Rectangle).
 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix if we set 
the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well? Currently 
if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the actual result 
in destination depends on what image was
painted first).
 - Should the clip be affected by the stroke(if it was set by the shape)? Right 
now if the clip was set by the shape it
will produce different result than if it was set via rectangle.

On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.







Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Jim Graham

[CC'ing Phil in case he has some suggestions for how the API should work...]

Responding just to additional questions in this email...

On 10/10/16 12:45 PM, Sergey Bylokhov wrote:

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix if we set 
the clip to the nearest areas they can
overlaps in the destination. Should we change the drawImage as well? Currently 
if I draw image to the nearest areas in
the user space, the images can overlap in the destination(so the actual result 
in destination depends on what image was
painted first).


Yes, I think adjacent drawImage requests should not overlap.  We should look 
into this separately.


 - Should the clip be affected by the stroke(if it was set by the shape)? Right 
now if the clip was set by the shape it
will produce different result than if it was set via rectangle.


I think we could have the clip never be affected by STROKE_NORMALIZE.  That might make sense because the NORMALIZE code 
is meant to deal with aesthetic issues, not rendering math issues.  We'd have to add a getClipSSI() method that 
hard-codes the "adjust" boolean to "false" to do that, but that is an easy fix.


The question is then that would meant that setClip(Shape) and fill(Shape) might disagree, though.  This would argue that 
we should have it affected by the normalization.  This is also a fairly easy fix, you could have LoopPipe have a method 
that would return the appropriate Rectangle representing which pixels are covered for a given Rectangle2D depending on 
the normalize parameters.


On the other hand, we normalize differently for AA and non-AA.  Calling getFillSSI() on LoopPipe basically performs 
normalization only for non-AA fills.  Arguably, though, clipping produces non-AA results in that it chooses whole pixels 
to include or exclude.  This might mean that it should never follow AA normalization.  But, it also points out the 
silliness of normalizing to match the results of fill when it can never do that for AA mode.  (Potentially we could add 
an AA-clip mode, but the implementation of that would require capturing every rendering operation to an intermediate 
buffer and then pixel-filtering it through a mask created by AA-filling the clip shape - we do that in FX, but it would 
require major surgery to add that to the SG2D pipeline so I don't think we would ever consider that at this stage.)


Any of those solutions are fairly easy to fix (except adding an AA clipping mode), but the question is which is more 
useful and/or surprises the developers the least.


So we have the current case:

setClip(integers or int-Rectangle) => pure coverage
setClip(other shape) => non-AA normalized coverage

If we decide that clip should normalize always to non-AA parameters because it is an intrinsically non-AA type of 
operation then we have to fix the setClip(integer rectangle) code which isn't hard.


If we decide that clip should normalize to the current AA parameters then it's basically the same, but we need to find a 
way to query the right objects to perform the AA according to their chosen bias.  LoopPipe/ShapeSpanIterator appear to 
own non-AA normalization and I think AA normalization is hidden behind the TileGenerator API somewhere that 
Ductus/Pisces/Marlin all implement.


If we decide that clip should not normalize then we only have to fix setClip(other shape) and it's just a question of 
hard-coding the adjust boolean in the call to instantiate the ShapeSpanIterator.


Phil?

...jim


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Sergey Bylokhov

An updated version:
http://cr.openjdk.java.net/~serb/8167310/webrev.03
 - STROKE_PURE is used in the test, the line width is set to 2.01. This 
also fixed the difference between clips(Shape vs Rectangle).

 - The if statement is changed as suggested.

The additional questions:
 - In the current fix we change behavior of the clip. Before the fix if 
we set the clip to the nearest areas they can overlaps in the 
destination. Should we change the drawImage as well? Currently if I draw 
image to the nearest areas in the user space, the images can overlap in 
the destination(so the actual result in destination depends on what 
image was painted first).
 - Should the clip be affected by the stroke(if it was set by the 
shape)? Right now if the clip was set by the shape it will produce 
different result than if it was set via rectangle.


On 10.10.16 22:29, Jim Graham wrote:

That does sound like a problem.  Does it do the same thing with new
Path2D(Rectangle)?  The Area class does some processing on the path and
it would be nice to eliminate that as a potential source of this
problem.  I don't have a buildable JDK9 repo right now that I can fire
off some quick tests on so I'll have to look at this later...

...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected
area. But in case of clip=rectangle all fillRects
produce the same areas.





--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Jim Graham
Yes, we do bias both.  So, the code we just added doesn't match the biasing that is performed by the fill operations, we 
should probably make it be the same.  You can see that it computes a bias boolean when it calls getFillSSI(), but the 
bias is applied natively in the native ShapeSpanIterator code...


...jim

On 10/10/16 12:26 PM, Sergey Bylokhov wrote:

On 10.10.16 22:04, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted, because the first and
last fillRects cover only the half of expected area. But in case of
clip=rectangle all fillRects produce the same areas.


It was solved by stroke=PURE, but I am not sure why fillRect(when clip is set 
via Shape) is affected by this hint. Is it
ok?




Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Jim Graham
That does sound like a problem.  Does it do the same thing with new Path2D(Rectangle)?  The Area class does some 
processing on the path and it would be nice to eliminate that as a potential source of this problem.  I don't have a 
buildable JDK9 repo right now that I can fire off some quick tests on so I'll have to look at this later...


...jim

On 10/10/16 12:04 PM, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think that the 
clip which is set via Shape is shifted,
because the first and last fillRects cover only the half of expected area. But 
in case of clip=rectangle all fillRects
produce the same areas.




Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Sergey Bylokhov

On 10.10.16 22:04, Sergey Bylokhov wrote:

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think
that the clip which is set via Shape is shifted, because the first and
last fillRects cover only the half of expected area. But in case of
clip=rectangle all fillRects produce the same areas.


It was solved by stroke=PURE, but I am not sure why fillRect(when clip 
is set via Shape) is affected by this hint. Is it ok?



--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Jim Graham



On 10/10/16 11:55 AM, Sergey Bylokhov wrote:

On 10.10.16 21:31, Jim Graham wrote:

OK, but you only need a line width of 2.0 to cover the gap regardless of
scale.  Line width scales in user space so larger scales scale up the
line width along with the clip region being rendered.  With
STROKE_CONTROL on, 2.0 is plenty because the line is normalized (though
I'm not sure the test should assume that).  WITH STROKE_PURE, 2.0 is
precisely exactly the right amount.  Round-off error might theoretically
bite us, so maybe 2.01 just to be safe.


When I tried to use w=2/3/4/5 I got a situation when no lines are drawn to the 
image. I guess to paint something we need
to cover at least half of the pixel, this is not the case when line is w=2 and 
small scale is used.


I think I see the problem.

With STROKE_NORMALIZE and a very tiny scale and a small line width you will not reach the center of a pixel from the 
x,y=0.25 offset that our implementation normalizes lines to.  At .1 scale you'd need to cover .25 units to reach that 
pixel center so you'd need a larger line width.  Since only half of the line happens on either side of the line, a line 
width of 5 at .1 scale only draws .25 on either side and even though that reaches the pixel center, it doesn't light up 
the pixel center because that would be the right (or bottom) side of the fillable area and a pixel is not rendered if 
its center falls on the right or bottom edge of a fillable region, so you would need to go to 6 to see something at .1 
scale.  If you turn off NORMALIZE and use PURE, then the line would track along with the clip location.


I'm not sure why you are testing NORMALIZE behavior since the NORMALIZE behavior is not a formal spec since there are 
several ways to achieve its goals.  The way we implement it 6 is enough for the lines to appear at .1 scale, but someone 
else might decide that normalizing lines to the pixel edges is better for some reason and then you'd need to have a line 
width of 11 to light up the pixels.  Note that we use 0.5,0.5 for AA rendering because its needs are different, so our 
own implementation isn't even consistent about the bias used for NORMALIZE (though since you aren't testing AA, you will 
only encounter our 0.25 bias).


If you switch to PURE then 2 (or 2.01 to be safe) would suffice...

...jim


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Sergey Bylokhov

On 10.10.16 21:55, Sergey Bylokhov wrote:

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


surprisingly but it is produce the different results And I think 
that the clip which is set via Shape is shifted, because the first and 
last fillRects cover only the half of expected area. But in case of 
clip=rectangle all fillRects produce the same areas.



--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Sergey Bylokhov

On 10.10.16 21:31, Jim Graham wrote:

OK, but you only need a line width of 2.0 to cover the gap regardless of
scale.  Line width scales in user space so larger scales scale up the
line width along with the clip region being rendered.  With
STROKE_CONTROL on, 2.0 is plenty because the line is normalized (though
I'm not sure the test should assume that).  WITH STROKE_PURE, 2.0 is
precisely exactly the right amount.  Round-off error might theoretically
bite us, so maybe 2.01 just to be safe.


When I tried to use w=2/3/4/5 I got a situation when no lines are drawn 
to the image. I guess to paint something we need to cover at least half 
of the pixel, this is not the case when line is w=2 and small scale is used.



In the drawImage case in the test, is there a reason to stretch the
image to MAX_INT size?  Isn't (img,0,0,null) enough? The issue with the
MAX_INT arguments is that this then becomes not only a test of clipping,
but a test for how our image scaling handles huge scales that might
overflow.  Those should be tested independently if we fear there is a
problem with image scaling.


This is extreme case which I tried to test, intersect the clip + the 
scale on graphics + the scale from drawImage, since this huge 
coordinates also can affect the clip, if intersection will be done 
incorrectly.




Also, This line in the test case:

 161 if (rgb != goldRGB && rgb != GREEN.getRGB()
 162 && rgb != RED.getRGB()) {

Will give us a pass on the test as long as we made the same mistake for
both the rect clip and the shape clip.  I think you want "(rgb !=
goldRGB) || (rgb != GREEN && rgb != RED)"...?


Correct, I will update the test.


--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-10 Thread Jim Graham

Hi Sergey,

Comments inline...

On 10/8/16 2:15 PM, Sergey Bylokhov wrote:

On 08.10.16 0:58, Jim Graham wrote:

That looks great.  A couple of questions.


An updated version and a comments inline:
http://cr.openjdk.java.net/~serb/8167310/webrev.01


Test case:

Where do you get white gaps?  Is it in the line test?  If so, then
consider setting the line width higher (or drawing 2 lines per iteration
as I mention in the last paragraph).  I can illustrate this with the
following:


Yes, it was in the lines. In the new version I changed the line width to 6. 
This value will fill the whole clip in all
tested scales[0.1 - 4].
I did not use two lines because I use "srcover+transparentColor" and two lines 
can produce one more color after
overlapping.


OK, but you only need a line width of 2.0 to cover the gap regardless of scale.  Line width scales in user space so 
larger scales scale up the line width along with the clip region being rendered.  With STROKE_CONTROL on, 2.0 is plenty 
because the line is normalized (though I'm not sure the test should assume that).  WITH STROKE_PURE, 2.0 is precisely 
exactly the right amount.  Round-off error might theoretically bite us, so maybe 2.01 just to be safe.


Other comments...

In the drawImage case in the test, is there a reason to stretch the image to MAX_INT size?  Isn't (img,0,0,null) enough? 
 The issue with the MAX_INT arguments is that this then becomes not only a test of clipping, but a test for how our 
image scaling handles huge scales that might overflow.  Those should be tested independently if we fear there is a 
problem with image scaling.


Also, This line in the test case:

 161 if (rgb != goldRGB && rgb != GREEN.getRGB()
 162 && rgb != RED.getRGB()) {

Will give us a pass on the test as long as we made the same mistake for both the rect clip and the shape clip.  I think 
you want "(rgb != goldRGB) || (rgb != GREEN && rgb != RED)"...?


...jim


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-08 Thread Sergey Bylokhov

On 08.10.16 0:58, Jim Graham wrote:

That looks great.  A couple of questions.


An updated version and a comments inline:
http://cr.openjdk.java.net/~serb/8167310/webrev.01



Region, line 132: why are you testing for newv > coordinate?


That was an attempt to catch an overflow like in case of int/longs. This 
is an unnecessary for double type, the code is removed and a spec of the 
method is also updated.



Test case:

Where do you get white gaps?  Is it in the line test?  If so, then
consider setting the line width higher (or drawing 2 lines per iteration
as I mention in the last paragraph).  I can illustrate this with the
following:


Yes, it was in the lines. In the new version I changed the line width to 
6. This value will fill the whole clip in all tested scales[0.1 - 4].
I did not use two lines because I use "srcover+transparentColor" and two 
lines can produce one more color after overlapping.



Note that this will cover some pixels to the left of the clip (which
should be clipped out), but it will leave a gap between the right side
of the line and the right side of the clip, i.e. the next step (of about
0.75 pixels - which are likely to include a pixel center and thus leave
a white pixel).  At higher scales, the gap will be higher and more
likely to include white pixels.

A line width of 2 (actually 2*stepsize where stepsize=1 here) means that
the line will cover an entire step regardless of the scale.  Hopefully
that will remove the need for the WHITE test in the validate method.

Note that STROKE_CONTROL may come into play here as well.  The above
analysis is for STROKE_PURE semantics, but the normalization/biasing of
STROKE_NORMALIZE might increase or decrease the chance that the above
will fix the issue and may require an even larger line width.

Another option without setting line width would be to draw two lines,
one at step and another at step+1, which would test for gaps between
adjacent lines as well as ensure that the test covers the "right half"
of the line at step and the "left half" of the line at step+1...

...jim

On 10/7/16 6:18 AM, Sergey Bylokhov wrote:

Hello.

Please review the fix for jdk9.

This is bug which was found when the fractional scale is used in
Swing. The problem is that if we save a usrClip as
Rectangle2D then we incorrectly intersect it with device clip. The
problem is in the RectangularShape.getBounds()
method, see more details:
http://mail.openjdk.java.net/pipermail/2d-dev/2016-July/007299.html

So getBounds() produces the bigger Rectangle than is necessary and our
clip became bigger as well. This means that in
some fractional scales such clips are overlapping.

The test will test fillRect, DrawImage, DrawLine methods and validates
that there are no any overlapping if we set the
clip.(The gaps between touched pixels are allowed only for lines).

Note that as I understand the code this fix should affect the
DrawLines, because in some situations it is possible that
two lines are overlapped without clip. And two other cases(fillRect,
drawImage) should work without clip, but only
fillRect works. It is discussed here:
http://mail.openjdk.java.net/pipermail/2d-dev/2016-October/007766.html


Bug: https://bugs.openjdk.java.net/browse/JDK-8167310
Webrev can be found at:
http://cr.openjdk.java.net/~serb/8167310/webrev.00




--
Best regards, Sergey.


Re: [OpenJDK 2D-Dev] [9] Review Request: 8167310 The graphics clip is incorrectly rounded for some fractional scales

2016-10-07 Thread Jim Graham

That looks great.  A couple of questions.

Region, line 132: why are you testing for newv > coordinate?

Test case:

Where do you get white gaps?  Is it in the line test?  If so, then consider setting the line width higher (or drawing 2 
lines per iteration as I mention in the last paragraph).  I can illustrate this with the following:


scale = 1.5
vertical line drawn with step, 0, step, SIZE covers the area:
(step-0.5)*1.5, -0.5, (step+0.5)*1.5, SIZE+0.5
step*1.5-.75, ..., step*1.5+0.75
clipLoX-0.75, ..., clipHiX-0.75

Note that this will cover some pixels to the left of the clip (which should be clipped out), but it will leave a gap 
between the right side of the line and the right side of the clip, i.e. the next step (of about 0.75 pixels - which are 
likely to include a pixel center and thus leave a white pixel).  At higher scales, the gap will be higher and more 
likely to include white pixels.


A line width of 2 (actually 2*stepsize where stepsize=1 here) means that the line will cover an entire step regardless 
of the scale.  Hopefully that will remove the need for the WHITE test in the validate method.


Note that STROKE_CONTROL may come into play here as well.  The above analysis is for STROKE_PURE semantics, but the 
normalization/biasing of STROKE_NORMALIZE might increase or decrease the chance that the above will fix the issue and 
may require an even larger line width.


Another option without setting line width would be to draw two lines, one at step and another at step+1, which would 
test for gaps between adjacent lines as well as ensure that the test covers the "right half" of the line at step and the 
"left half" of the line at step+1...


...jim

On 10/7/16 6:18 AM, Sergey Bylokhov wrote:

Hello.

Please review the fix for jdk9.

This is bug which was found when the fractional scale is used in Swing. The 
problem is that if we save a usrClip as
Rectangle2D then we incorrectly intersect it with device clip. The problem is 
in the RectangularShape.getBounds()
method, see more details:
http://mail.openjdk.java.net/pipermail/2d-dev/2016-July/007299.html

So getBounds() produces the bigger Rectangle than is necessary and our clip 
became bigger as well. This means that in
some fractional scales such clips are overlapping.

The test will test fillRect, DrawImage, DrawLine methods and validates that 
there are no any overlapping if we set the
clip.(The gaps between touched pixels are allowed only for lines).

Note that as I understand the code this fix should affect the DrawLines, 
because in some situations it is possible that
two lines are overlapped without clip. And two other cases(fillRect, drawImage) 
should work without clip, but only
fillRect works. It is discussed here:
http://mail.openjdk.java.net/pipermail/2d-dev/2016-October/007766.html


Bug: https://bugs.openjdk.java.net/browse/JDK-8167310
Webrev can be found at: http://cr.openjdk.java.net/~serb/8167310/webrev.00