Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
uts (but not at the > >>>> same > >>>>>> time). > >>>>>> This could no longer be supported with this approach. > >>>>>> The way I did it has none of these weaknesses. > >>>>>> > >>>>>> 2. As for algorithms for the circle approximation, I considered > 2: > >>>>>> a. Compute the control points using the constraints that > >>>>>> B(1/3)=A(a+t/3) > >>>>>> and B(2/3) = A(a+2t/3) (i.e. make the arc and the bezier curve > >>>>>> coincide at 2 > >>>>>> evenly spaced points in the arc). This didn't work very well: > some > >>>> of > >>>>>> the end > >>>>>> caps looked more like triangles. > >>>>>> b. Let B(1/2) = A(a+t/2), and B'(1/2) = A'(a+t/2). This > worked > >>>>>> better, but > >>>>>> still not good enough. > >>>>>> > >>>>>> If anyone knows of any better ways to compute the control > points, > >>>>>> please let > >>>>>> me know. > >>>>>> > >>>>>> I'm sorry for the length of this. I tried to make it shorter. > >>>>>> > >>>>>> Thank you very much, > >>>>>> Denis. > >>>>>> > >>>>>> > >>>>>> - "Jim Graham" wrote: > >>>>>> > >>>>>>> Hi Denis, > >>>>>>> > >>>>>>> Consider the case of using BasicStroke.createStrokedShape(). > How > >>>> do > >>>>>>> you > >>>>>>> know how many pixels the resulting path will occupy? You > can't > >>>>>> reduce > >>>>>>> to concrete samples if you don't know the transform. > >>>>>>> > >>>>>>> So, for rendering, then you may be correct. But for cases > where > >>>> the > >>>>>>> path is being asked for then beziers are the only responsible > >>>>>>> solution... > >>>>>>> > >>>>>>> ...jim > >>>>>>> > >>>>>>> Denis Lila wrote: > >>>>>>>> Hello Jim. > >>>>>>>> > >>>>>>>> I thought about checking the output and changing the > behaviour > >>>>>>>> depending on whether the output is a PC2D or a LineSink, but > I > >>>>>>> didn't > >>>>>>>> implement it because I thought the point was to get rid of > the > >>>>>>> sampling > >>>>>>>> at this stage. However, if performance is the issue, then I > >>>> guess > >>>>>>> I'll > >>>>>>>> start working on it. > >>>>>>>> > >>>>>>>> Although, I wonder whether it is really worth it. I think > most > >>>>>> lines > >>>>>>> drawn > >>>>>>>> won't be wider than about 5 pixels, which means that the > current > >>>>>> way > >>>>>>> will > >>>>>>>> emit about 7 lines, so that's 14 coordinates. 2 bezier > quarter > >>>>>>> circles will > >>>>>>>> require 12 coordinates. In terms of storage, there isn't > much > >>>>>>> difference, and > >>>>>>>> for lines of width 4 or smaller the current method is more > >>>>>>> efficient. > >>>>>>>> I'm also guessing that it's harder for the rasterizer to > deal > >>>> with > >>>>>>> bezier > >>>>>>>> curves than with straight lines, so is it possible that > >>>> replacing > >>>>>>> the > >>>>>>>> 3.14*lineWidth/2 lines generated by the current method with > 2 > >>>>>> bezier > >>>>>>>> quarter circles isn't worth it (for small lineWidths)? > >>>>>>>> > >>>>>>>> Thanks, > >>>>>>>> Denis. > >>>&g
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
straight lines, so is it possible that replacing the 3.14*lineWidth/2 lines generated by the current method with 2 bezier quarter circles isn't worth it (for small lineWidths)? Thanks, Denis. - "Jim Graham" wrote: 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 drawing round endcaps on scaled lines.
'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 drawing round endcaps on scaled lines.
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 drawing round endcaps on scaled lines.
here isn't much difference, and for lines of width 4 or smaller the current method is more efficient. I'm also guessing that it's harder for the rasterizer to deal with bezier curves than with straight lines, so is it possible that replacing the 3.14*lineWidth/2 lines generated by the current method with 2 bezier quarter circles isn't worth it (for small lineWidths)? Thanks, Denis. - "Jim Graham" wrote: 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.wikip
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
on whether the output is a PC2D or a LineSink, but I > >>> didn't > >>>> implement it because I thought the point was to get rid of the > >>> sampling > >>>> at this stage. However, if performance is the issue, then I > guess > >>> I'll > >>>> start working on it. > >>>> > >>>> Although, I wonder whether it is really worth it. I think most > >> lines > >>> drawn > >>>> won't be wider than about 5 pixels, which means that the current > >> way > >>> will > >>>> emit about 7 lines, so that's 14 coordinates. 2 bezier quarter > >>> circles will > >>>> require 12 coordinates. In terms of storage, there isn't much > >>> difference, and > >>>> for lines of width 4 or smaller the current method is more > >>> efficient. > >>>> I'm also guessing that it's harder for the rasterizer to deal > with > >>> bezier > >>>> curves than with straight lines, so is it possible that > replacing > >>> the > >>>> 3.14*lineWidth/2 lines generated by the current method with 2 > >> bezier > >>>> quarter circles isn't worth it (for small lineWidths)? > >>>> > >>>> Thanks, > >>>> Denis. > >>>> > >>>> - "Jim Graham" wrote: > >>>> > >>>>> 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 Sh
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
t;> evenly spaced points in the arc). This didn't work very well: some > of > >>> the end > >>> caps looked more like triangles. > >>> b. Let B(1/2) = A(a+t/2), and B'(1/2) = A'(a+t/2). This > worked > >>> better, but > >>> still not good enough. > >>> > >>> If anyone knows of any better ways to compute the control points, > >>> please let > >>> me know. > >>> > >>> I'm sorry for the length of this. I tried to make it shorter. > >>> > >>> Thank you very much, > >>> Denis. > >>> > >>> > >>> - "Jim Graham" wrote: > >>> > >>>> Hi Denis, > >>>> > >>>> Consider the case of using BasicStroke.createStrokedShape(). How > do > >>>> you > >>>> know how many pixels the resulting path will occupy? You can't > >>> reduce > >>>> to concrete samples if you don't know the transform. > >>>> > >>>> So, for rendering, then you may be correct. But for cases where > the > >>>> path is being asked for then beziers are the only responsible > >>>> solution... > >>>> > >>>> ...jim > >>>> > >>>> Denis Lila wrote: > >>>>> Hello Jim. > >>>>> > >>>>> I thought about checking the output and changing the behaviour > >>>>> depending on whether the output is a PC2D or a LineSink, but I > >>>> didn't > >>>>> implement it because I thought the point was to get rid of the > >>>> sampling > >>>>> at this stage. However, if performance is the issue, then I > guess > >>>> I'll > >>>>> start working on it. > >>>>> > >>>>> Although, I wonder whether it is really worth it. I think most > >>> lines > >>>> drawn > >>>>> won't be wider than about 5 pixels, which means that the > current > >>> way > >>>> will > >>>>> emit about 7 lines, so that's 14 coordinates. 2 bezier quarter > >>>> circles will > >>>>> require 12 coordinates. In terms of storage, there isn't much > >>>> difference, and > >>>>> for lines of width 4 or smaller the current method is more > >>>> efficient. > >>>>> I'm also guessing that it's harder for the rasterizer to deal > with > >>>> bezier > >>>>> curves than with straight lines, so is it possible that > replacing > >>>> the > >>>>> 3.14*lineWidth/2 lines generated by the current method with 2 > >>> bezier > >>>>> quarter circles isn't worth it (for small lineWidths)? > >>>>> > >>>>> Thanks, > >>>>> Denis. > >>>>> > >>>>> - "Jim Graham" wrote: > >>>>> > >>>>>> 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 > >>>>
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
eeding 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 drawing round endcaps on scaled lines.
y, 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 drawing round endcaps on scaled lines.
. This worked better, but still not good enough. If anyone knows of any better ways to compute the control points, please let me know. I'm sorry for the length of this. I tried to make it shorter. Thank you very much, Denis. - "Jim Graham" wrote: Hi Denis, Consider the case of using BasicStroke.createStrokedShape(). How do you know how many pixels the resulting path will occupy? You can't reduce to concrete samples if you don't know the transform. So, for rendering, then you may be correct. But for cases where the path is being asked for then beziers are the only responsible solution... ...jim Denis Lila wrote: Hello Jim. I thought about checking the output and changing the behaviour depending on whether the output is a PC2D or a LineSink, but I didn't implement it because I thought the point was to get rid of the sampling at this stage. However, if performance is the issue, then I guess I'll start working on it. Although, I wonder whether it is really worth it. I think most lines drawn won't be wider than about 5 pixels, which means that the current way will emit about 7 lines, so that's 14 coordinates. 2 bezier quarter circles will require 12 coordinates. In terms of storage, there isn't much difference, and for lines of width 4 or smaller the current method is more efficient. I'm also guessing that it's harder for the rasterizer to deal with bezier curves than with straight lines, so is it possible that replacing the 3.14*lineWidth/2 lines generated by the current method with 2 bezier quarter circles isn't worth it (for small lineWidths)? Thanks, Denis. - "Jim Graham" wrote: 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 do
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
; > >>> 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 drawing round endcaps on scaled lines.
mediate 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 drawing round endcaps on scaled lines.
r 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 drawing round endcaps on scaled lines.
don't know the transform. > > So, for rendering, then you may be correct. But for cases where the > path is being asked for then beziers are the only responsible > solution... > > ...jim > > Denis Lila wrote: > > Hello Jim. > > > > I thought about checking the output and changing the behaviour > > depending on whether the output is a PC2D or a LineSink, but I > didn't > > implement it because I thought the point was to get rid of the > sampling > > at this stage. However, if performance is the issue, then I guess > I'll > > start working on it. > > > > Although, I wonder whether it is really worth it. I think most lines > drawn > > won't be wider than about 5 pixels, which means that the current way > will > > emit about 7 lines, so that's 14 coordinates. 2 bezier quarter > circles will > > require 12 coordinates. In terms of storage, there isn't much > difference, and > > for lines of width 4 or smaller the current method is more > efficient. > > > > I'm also guessing that it's harder for the rasterizer to deal with > bezier > > curves than with straight lines, so is it possible that replacing > the > > 3.14*lineWidth/2 lines generated by the current method with 2 bezier > > > quarter circles isn't worth it (for small lineWidths)? > > > > Thanks, > > Denis. > > > > - "Jim Graham" wrote: > > > >> 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 d
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
now 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 drawing round endcaps on scaled lines.
od, 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 drawing round endcaps on scaled lines.
Hi Denis, Consider the case of using BasicStroke.createStrokedShape(). How do you know how many pixels the resulting path will occupy? You can't reduce to concrete samples if you don't know the transform. So, for rendering, then you may be correct. But for cases where the path is being asked for then beziers are the only responsible solution... ...jim Denis Lila wrote: Hello Jim. I thought about checking the output and changing the behaviour depending on whether the output is a PC2D or a LineSink, but I didn't implement it because I thought the point was to get rid of the sampling at this stage. However, if performance is the issue, then I guess I'll start working on it. Although, I wonder whether it is really worth it. I think most lines drawn won't be wider than about 5 pixels, which means that the current way will emit about 7 lines, so that's 14 coordinates. 2 bezier quarter circles will require 12 coordinates. In terms of storage, there isn't much difference, and for lines of width 4 or smaller the current method is more efficient. I'm also guessing that it's harder for the rasterizer to deal with bezier curves than with straight lines, so is it possible that replacing the 3.14*lineWidth/2 lines generated by the current method with 2 bezier quarter circles isn't worth it (for small lineWidths)? Thanks, Denis. - "Jim Graham" wrote: 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.o
Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
Hello Jim. I thought about checking the output and changing the behaviour depending on whether the output is a PC2D or a LineSink, but I didn't implement it because I thought the point was to get rid of the sampling at this stage. However, if performance is the issue, then I guess I'll start working on it. Although, I wonder whether it is really worth it. I think most lines drawn won't be wider than about 5 pixels, which means that the current way will emit about 7 lines, so that's 14 coordinates. 2 bezier quarter circles will require 12 coordinates. In terms of storage, there isn't much difference, and for lines of width 4 or smaller the current method is more efficient. I'm also guessing that it's harder for the rasterizer to deal with bezier curves than with straight lines, so is it possible that replacing the 3.14*lineWidth/2 lines generated by the current method with 2 bezier quarter circles isn't worth it (for small lineWidths)? Thanks, Denis. - "Jim Graham" wrote: > 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 >
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 drawing round endcaps on scaled lines.
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 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.
[OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.
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.exporting patch: # HG changeset patch # User Denis Lila # Date 1276110761 14400 # Node ID 5cc40c7f2678d320519013b58af6808a0516cd68 # Parent 4d55419ce99e749da5037fa4d8247117f1a5cc2e Fixed bug http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=506 diff --git a/src/share/classes/sun/java2d/pisces/Stroker.java b/src/share/classes/sun/java2d/pisces/Stroker.java --- a/src/share/classes/sun/java2d/pisces/Stroker.java +++ b/src/share/classes/sun/java2d/pisces/Stroker.java @@ -209,7 +209,34 @@ this.miterLimitSq = (long)(limitSq*65536.0*65536.0); } -this.numPenSegments = (int)(3.14159f*lineWidth/65536.0f); +// The pen is a circle mapped through the linear transformation +// this.transform; therefore, we must calculate the circumference +// of the mapped pen, not the pen. If we calculate the +// circumference of the pen without taking into account this.transform +// the round end caps will look jagged. However, the way I calculate +// the circumference of the mapped pen is just a crude approximation, so +// if anyone reading this knows how to better compute the circumference +// of ellipses, please fix it. + +// So, we map the points (1,0), (0,1), (-1,0), and (0,-1) through +// the transformation. The results are (m00,m10), (m01,m11), +// (-m00,-m01), and (-m01,-m11). We simply calculate the lengths of +// the mapped horizontal and vertical diameters, scale them by the +// actual radius of the circle (i.e. lineWidth / 2), calculate the +// circumference of a circle whose diameter is the greater of those +// two, and pretend this calculation is a good enough approximation +// to the circumference of the mapped circle. +double dx1 = 2*dm00; +double dy1 = 2*dm10; +double dx2 = 2*dm01; +double dy2 = 2*dm11; +double radius = lineWidth / (2 * 65536.0); +// The diameters: +double mappedD1 = radius * java.lang.Math.sqrt(dx1*dx1 + dy1*dy1); +double mappedD2 = radius * java.lang.Math.sqrt(dx2*dx2 + dy2*dy2); +double mappedD = (mappedD1 < mappedD2) ? mappedD2 : mappedD1; + +this.numPenSegments = (int) (3.14159 * mappedD); if (pen_dx == null || pen_dx.length < numPenSegments) { this.pen_dx = new int[numPenSegments]; this.pen_dy = new int[numPenSegments];