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