Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
Sigh - that makes sense. One issue is that the resulting paths it generates are much more "verbose" than they need to be. This would generally mean that it takes far more storage than it would otherwise need - and it means that if the result needs to be transformed then it would take many more computations to transform each segment than the bezier. So, perhaps it would be worth having it check the type of the output and do either a bezier or a bunch of lines depending on if it is a PC2D or a LineSink? Also, it isn't really that difficult to for Renderer to include its own Cubic/Quadratic flattening code, but it might involve more calculations than the round-cap code since it would have to be written for arbitrary beziers whereas if you know it is a quarter circle then it is easier to know how far to subdivide... :-( ...jim Denis Lila wrote: So, I have been thinking about this, and I can't see a good way to do it that wouldn't involve heavy changes to Pisces. In order for Stroker to generate Bezier quarter circles, it would have to implement a curveTo method, which means Stroker should start implementing PathConsumer2D and instead of using a LineSink output it would have to use a PathConsumer2D output (either that, or LineSink should include a curveTo method, but then there won't really be any difference between a LineSink and a PathConsumer2D. By the way, LineSink doesn't have any implemented methods, so why is it an abstract class as opposed to an interface?) Stroker is used in 3 ways: 1. As an implementation of BasicStroke's createStrokedShape method. This uses a Path2D object as output. 2. As a way of feeding a PathConsumer2D without calling createStrokedShape to generate an intermediate Shape. This uses a PathConsumer2D output. 3. As a way of feeding lines to a Renderer object, which generates alpha tiles used for anti-aliasing that are fed to a cache and extracted as needed by an AATileGenerator. Obviously, Stroker's output here is a Renderer. 1 and 2 aren't problems, because the underlying output objects support Bezier curves. 3, however, doesn't, and it seems like implementing a curveTo method for Renderer would be very difficult because the way it generates alpha tiles is by scanning the drawn edges with horizontal scan lines, and for each scan line finding the x-intersections of the scan lines and the edges. Then it determines the alpha values (I'm not too sure how it does this). In order to implement Bezier curves in Renderer, we would have to have a quick way of computing, for each scan line, all its intersections with however many Bezier curves are being drawn. I haven't given much thought to how this could be done, as I am not very familiar with Bezier curves, but it doesn't seem easy enough to justify fixing such a small bug. - Original Message - From: "Jim Graham" To: "Denis Lila" Cc: 2d-dev@openjdk.java.net Sent: Wednesday, June 9, 2010 7:42:33 PM GMT -05:00 US/Canada Eastern Subject: Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines. I don't understand - why do we generate sample points based on the size of the cap? Why not generate a pair of bezier quarter-circles and let the rasterizer deal with sampling? ...jim Denis Lila wrote: Hello. I think I have a fix for this bug: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=506 Basically, the problem is that if there is a magnifying affine transformation set on the graphics object and one tries to draw a line with small thickness and round end caps, the end caps appear jagged. This is because the computation of the length of the array that contains the points on the "pen" with which the decoration is drawn does not take into account the size of the pen after the magnification of the affine transformation. So, for example, if the line length was set to 1, and the transformation was a scaling by 10, the resulting pen would have a diameter of 10, but only 3 pen points would be computed (pi*untransformedLineWidth), so the end cap looks like a triangle. My fix computes an approximation of the circumference of the transformed pen (which is an ellipse) and uses that as the number of points on the pen. The approximation is crude, but it is simple, faster than alternatives (http://en.wikipedia.org/wiki/Ellipse#Circumference), and I can say from observations that it works fairly well. There is also icing on the cake, in the form of slight improvements in performance when the scaling is a zooming out. Example: if the original line width was 100, but g2d.scale(0.1,0.1) was set, then the resulting line would have a width of 10, so only ~31 points are necessary for the decoration to look like a circle, but without this patch, about 314 points are computed (and a line is emitted to each one of them). I appreciate any feedback. Regards, Denis Lila.
Re: [OpenJDK 2D-Dev] Fix for uniformly scaled dashed lines.
Hi Denis, Here are my thoughts on it: - Lines are affinely transformed into lines. The slope may be different before and after the transform, but both have a single slope. - The ratio of a line length to its transformed line length is a scale factor that depends solely on the angle of the line. Thus, for determining dashing you can simply compute this scale factor once for a given line and then that single scale factor can be applied to every dash segment. It appears that your setup code takes these factors into account, though I haven't done a grueling line by line analysis as to whether you got the math right. One more optimization is that once you know the angle of the line then you have a factor for how the length of a segment of that line relates to its dx and dy. Note that for horizontal and vertical lines one of those factors may be Infinity, but every line will have a non-zero and non-infinity factor for one of those two dimensions. This means that you can calculate the dashing by simply looping along the major axis of the line and comparing either the dx, or the dy to scaled "lengths" that represent the lengths of the transformed dashes projected onto the major axis. Finally, the other dx,dy can be computed from the dx,dy of the major axis with another scale. I am pretty sure that this dx=>dy or dy=>dx scale factor might be zero, but it would never be infinite if you are calculating along the major axis of the transformed line, but I didn't write out a proof for it. Taking both of these concepts into account - can that make the inner loop even simpler? ...jim Denis Lila wrote: Hello. I think I have a fix for this bug: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=504 The problem is caused by the "symmetric" variable in pisces/Dasher.java. symmetric is set to (m00 == m11 && m10 == -m01), and never changed. It is only used in one place (in lineTo) to simplify the computation of the length of the line before an affine transformation A was applied to it. This is why it causes a problem: If A = [[a00, a01], [a10, a11]] and (x,y) is a point obtained by applying A to some other point (x',y'), then what we want is the length of the vector (x',y'), which is ||Ainv*(x,y)||. Ainv = (1/det(A)) * [[a11, -a01],[-a10, a00]], so, after some calculations, ||Ainv*(x,y)|| ends up being equal to sqrt(x^2*(a11^2 + a10^2) + y^2*(a00^2 + a01^2) - x*y*(a11*a01 + a00*a10)) * 1/|det(A)|. If symmetric==true, this simplifies to: sqrt((a11^2 + a01^2) * (x^2 + y^2)) * 1/|det(A)|, and |det(A)| = a11^2 + a01^2, so, the final answer is: sqrt((x^2 + y^2)) / sqrt(det(A)). Therefore the problem in Dasher.java is that it divides by det(A), not sqrt(det(A)). My fix for this was to remove the "symmetric" special case. Another possible fix would have been to introduce an instance "sqrtldet" and set it to sqrt(det(A)), and divide by that instead of det(A). This didn't seem worth it, because the only benefit we gain by having the "symmetric" variable is to save 3 multiplications and 1 division per iteration of the while(true) loop, at the expense of making the code more complex, harder to read, introducing more opportunity for bugs, and adding hundreds of operations of overhead (since PiscesMath.sqrt would have to be called to initialize sqrtldet). To make up for this slight performance loss I have moved the code that computes the transformed dash vectors outside of the while loop, since they are constant and they only need to be computed once for any one line. Moreover, computing the constant dash vectors inside the loop causes them to not really be constant (since they're computed by dividing numbers that aren't constant). This can cause irregularities in dashes (see comment 14 in http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=197). I would very much appreciate any comments/suggestions. Thank you, Denis Lila.
Re: [OpenJDK 2D-Dev] [OpenJDK Rasterizer] Antialiased horizontal or vertical lines.
The Ductus pipeline will do the same thing with STROKE_PURE. It sounds like maybe the Pisces pipeline doesn't support STROKE_NORMALIZE yet? ...jim Denis Lila wrote: Hello. I noticed that anti aliased horizontal and vertical lines are not drawn properly. I've described the results (with pictures) here: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=509 In the patch, I try shifting line coordinates by half a pixel as soon as they're passed into Renderer.java:lineTo, and it seems to fix it. However, this seems a bit too easy, so if anyone can think of any ways in which this fix breaks something, please let me know. Thank you, Denis.
[OpenJDK 2D-Dev] Antialiased horizontal or vertical lines.
Hello. I noticed that anti aliased horizontal and vertical lines are not drawn properly. I've described the results (with pictures) here: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=509 In the patch, I try shifting line coordinates by half a pixel as soon as they're passed into Renderer.java:lineTo, and it seems to fix it. However, this seems a bit too easy, so if anyone can think of any ways in which this fix breaks something, please let me know. Thank you, Denis.exporting patch: # HG changeset patch # User Denis Lila # Date 1276894582 14400 # Node ID 69032d725302bc9fa243e6e7ccc843577472b2ff # Parent be909a137c8ee9faf46de0c1812d68828ee0522b 509 fix. diff --git a/src/share/classes/sun/java2d/pisces/Renderer.java b/src/share/classes/sun/java2d/pisces/Renderer.java --- a/src/share/classes/sun/java2d/pisces/Renderer.java +++ b/src/share/classes/sun/java2d/pisces/Renderer.java @@ -174,6 +174,8 @@ this.x0 = x1; return; } +x1 += 32768; +y1 += 32768; int orientation = (y0 < y1) ? 1 : -1; if (lastOrientation == 0) {
[OpenJDK 2D-Dev] hg: jdk7/2d/jdk: 6961633: gui applications cause a jvm crash on windows
Changeset: 83c7768292d7 Author:prr Date: 2010-06-18 11:00 -0700 URL: http://hg.openjdk.java.net/jdk7/2d/jdk/rev/83c7768292d7 6961633: gui applications cause a jvm crash on windows Reviewed-by: ceisserer, bae ! make/sun/pisces/Makefile ! src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine + src/solaris/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine