From bourges.laurent at gmail.com Fri Sep 1 20:56:17 2017 From: bourges.laurent at gmail.com (=?UTF-8?Q?Laurent_Bourg=C3=A8s?=) Date: Fri, 1 Sep 2017 22:56:17 +0200 Subject: [OpenJDK 2D-Dev] Fwd: RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0 In-Reply-To: References: <342d141a-da55-520b-dae0-c87fbb990a98@oracle.com> <2a2436e3-ac17-f7e3-1088-bd60205cb6e6@oracle.com> <1a80ab24-db5a-9708-e53a-2af277c5bc76@oracle.com> <034d753b-599c-f4c0-f4fa-0a7fa47e76a7@oracle.com> Message-ID: CCing the mailing-lists Hi Jim, I read carefully your very good inputs on clipping / filtering in both Renderer or PreFilter. Here are my comments (in the discussion order): On 8/31/17 4:15 PM, Jim Graham wrote: > > - It can stop processing when it reaches the right edge of the clip as the > crossings out there have no impact on anything that will be rendered > Not exactly, the Renderer needs at least one crossing on the right side to determine the current span end. However, I added a shortcut to quickly exit from the loop on the right side. To act as you said, a post loop code should be added to see if the count is > 0 and that would mean the current span should be emitted until the right side. > The only thing missing for curves is that they might be rejected in their > entirety, or we might be able to pare them down to only the pieces that > need to be processed. Currently they will be rejected as they feed their > pieces to addLine() and it rejects each segment in turn, but we might be > able to short circuit the process by looking at their control points up > front before we run DDA on them. > I totally agree and I already implemented such quad/curve shortcut in my own Renderer variant (minor gain) and that could benefit to either Stroker and the filling case notably on the left / right sides. > If a curve is more complicated in how it interacts with the > top/bot/left/right clip coordinates, then it might still be rejected, or it > might need to be partially rendered. Something is going to need to do some > computation to figure that out. If we try to do those computations before > we get to the Renderer, then whatever computations we use to do that will > likely be just as complicated as the DDA work done inside the Renderer. > That work as a "pre-filter" will also be complicated in that it will then > need to express its results as a "simplified, but connected" path rather > than simply dropping pieces on the floor as the Renderer can do. > Agreed. I do not want to duplicate such complicated code, only 80% gain (pareto rule) so my current PathClipFilter only rejects trivial segments and rely on the Renderer to efficiently deal with more complex cases. > Now, it is possible that we could sub-divide a curve that has no simple > out-code rejection criteria - for example a curve that starts above the > clip, but horizontally "over" it, extends around the upper-right corner of > the clip to a position that is to the right of the clip, but within its > vertical bounds. Such a curve would not be rejected by any "all Y "all X>right" tests. It might be true that you could cut it at some point > on the curve (and you might even be lucky enough that a midpoint cut would > suffice) and each half of the curve would then pass the rejection criteria, > but you'd have to analyze the curve to figure that out. It is just as > likely that while the control points follow the pattern I outlined at the > start of this paragraph, the actual traced outline goes inside the clip. > You won't know until you perform some calculations. In the meantime, the > Renderer already does a pretty fast DDA subsection of the curve and those > pieces are then rejected by addLine() each in turn. How sure can you be > that you can find a computation for such curves that will be successful in > enough cases that you will save time over DDA? How often are curves even > in this particular situation in the first place? If only .1% of curves > ever benefit from this analysis then you might slow down the common case to > be slightly faster in a rare case. > As I said, let's try to Keep It Simple Silly for now. Although, I could later perform one subdivision step (line, quad, curve) for TOP <-> LEFT <-> BOTTOM <-> RIGHT transitions and try again a trivial reject test (all control points outside) but only for large enough curves / lines. It will benefit to large filled circles but I agree it is a corner case. > Finally, if there is some calculation that could be performed on such "not > immediately rejectable, but possibly outside" curves to simplify their > processing, the best place for those calculations is still in the Renderer > where its response to finding a piece of a curve that is trivially > rejectable is to just skip it, rather than a pre-filter which will have to > worry about how to connect the path around the skipped pieces. > I disagree: the Renderer class has already several variants (maintainability issue) and it very complex so I want to leave it untouched as most as possible and externalize that supplementary stage into the rendering pipeline. The Stroker webrev works like a charm and it already performs path filtering. Modifying the Renderer will mean that the path filtering will be done twice or that Stroker should indicate to not filter twice the segments ! > > So, in the end, I don't see any situation - including any calculation that > you think could help reject pieces faster - that would be better served as > a filter run ahead of Renderer that can't be more optimally done by adding > code to the Renderer and simply dropping pieces on the floor...? > I already tried to explain an interesting case: closed subpaths on the left or right sides are bringing lots of edges into the Renderer bag that cost a lot due to the scanline processing (crossing inc, sort, spans ...). I prefer coding an external simplifier compatible with Renderer, than complexifying the Renderer itself to record subpaths, test outcodes that would add more complexity, code lines... > > On 8/31/17 1:34 PM, Laurent Bourg?s wrote: > >> Another case: you provided a Test class using a path made with 10000 line >> segments on the left side. If it is converted by createStrokedShape(), then >> the Renderer will again deal with thousands crossings and it will be slow >> again. >> > > Such a case will already be handled by the clipping in the Stroker, though > - work that you've already done in these webrevs. > Yes that works well with Stroker. As I explained such huge polyline can be converted to a polygon by calling createStrokedShape() and then rendered by fill(shape): - unclipped: 300ms - (experimental) clipped path: 4ms (twice slower than Stroker as there is twice more segments as the shape was completely stroked) > For the Even-odd filling rule, I think it needs exact segment >> intersections on the left side, so I am focused on the Non-zero filling >> rule for now. >> > > They are identical. All that matters is that you have the proper starting > winding count as you enter the clip from the left. They could be replaced > by either a segment with the same "Y range" as I mention above, or they > could be replaced by having a value in the segments list that is "starting > count", so if you have a segment that is out-left and it goes from Y=10 to > Y=20, you simply add (or subtract for reversed lines) one to the "starting > count" field for all scanlines from 10->20. > I am still very skeptic with EO rule as I am not sure it was equivalent as shapes can have self intersections ... or curve / line intersections on the left side that could lead to different accumulated count. After reading several times your explanations, I understand that on the left side (outside): - curves / quads can be simplified to a simple line (P0 to P3), but what about intersections in the middle of the curves ? should the Y range be set to min(curveY), max(curveY) that is not easy to solve ... - quad/curve/line segments can not be skipped with the EO rule to preserve the Y ranges properly. Am I right ? Maybe your later approach is interesting to introduce a new starting_counts array along the Y axis to increment / decrement and then it would be possible to totally ignore invisible segments on the left side ? > Finally I tried two approach: >> - basic subpath outside test (derived from the ClosedPathDetector) to >> ignore closed sub-paths outside of the clip. >> - more general clipper that follows the path, detect enter/exit the clip >> but it needs to insert/remove corner points. I am improving this latter >> approach. >> > > Consider that your filter that works ahead of the Renderer will need to > deal with the following issues: > > - detecting if the segments are out-top/bottom/right and drop them > - A filter will then need to worry how to connect those paths back to > the rest > - Renderer can just drop them, end of story > On right side, Renderer need a 'closing' span edge. > - detecting if the segments are out-left and manage the winding counts > - A filter will need to manage that plus it will have to connect the > paths > - Renderer can just do addLine() or adjust "scanline-starting-count", > end of story > But addLine() is the origin of the performance issue = extra cost of processing extra crossings ! > - worrying about paths that loop around the entire clip, perhaps winding > several times around the clip before they dive back into the clip rectangle > - A filter has to construct a meaningful path to represent that same > outcome > - Renderer just discards all pieces that aren't out-left and > just manages the "starting count" for just the out-left parts > Thanks for the filter specifications I am working on. I will find a compromise between rejecting segments and preserving accuracy while providing better performance for the NZ rule as EO seems too complicated to me (later ?). 2017-09-01 1:37 GMT+02:00 Jim Graham : > I had another thought here. > > If you have some plan where you can identify incoming paths as "probably > benefiting from more aggressive clipping logic" vs others that are > classified as "most likely will have little to no clipping" and you want to > avoid the overhead of having the early-rejection clipping logic on all > paths, then a simple tweak to the design of the Renderer would make it much > easier. > > Right now Renderer is both a "bag of segments with a scan-line sampling > loop" and it is also a PathConsumer2D. If you want to insert something > ahead of it, it makes logical sense to have that delegating class > communicate downstream to the Renderer via PathConsumer2D. > > But, we could remove the PathConsumer2D from Renderer and turn it into > just a "bag of segments" that is managed by an external PathConsumer2D > helper class. Basically, take all of the PC2D methods in Renderer and move > them into an UnclippedFiller class - just cut and paste. The new class > will need a pointer to a Renderer object and it will only call r.addLine() > and r.fooBreakIntoLines*() calls. It would actually be a very small class > since the PC2D interface was such a tiny portion of what Renderer > implemented. The new helper class will manage all > sub-path/moveto/close-path awareness on its own with the Renderer being > unaware of such distinctions. > > This should be computationally identical to the Renderer we have now - no > new methods are inserted, they are just moved to a different class. But by > separating out the PC2D methods into a separate class, we have the > flexibility to have different ways for the PC2D chain to interact with the > Renderer. > > This would let us create an analogous sister class - ClippedFiller - that > does the same thing, but adds some early rejection computations as well. > This is a simpler design than what you are attempting now because its > output is only "segments to add to the bag of segments", not "well-behaved > PC2D paths". > > But, if there is no easy way to identify paths up front as "we should > pre-clip this" or "not" then this isn't really needed - just add the > necessary logic to Renderer instead... > My Stroker webrev relies on the current Renderer ability to clip properly top/bottom and manages the shape boundaries. My PathClipFiller is only applied in the filling case (low overhead). As your approach is very generic, it would be a good idea to extract that clip part for better maintainability and simplify the Renderer code. However, the Renderer deals with subpixel coordinates so its clip is scaled and both addLine() and fooBreakIntoLines() should be adapted to handle the subpixel scaling factors. 2017-09-01 1:55 GMT+02:00 Jim Graham : > I want to elaborate on winding count issues for segments to the left of > the clip for both winding modes. > Thanks as it is not obvious to me ! All curves have the property that the winding count of any sample point to > the right of them is identical to the winding count of a line from their > starting point to their ending point. > > Consider a quad. If it is monotonic, then the observation should be > fairly obvious as the curve only ever has one crossing for any scanline and > only the X location of that crossing varies and it only varies within the > bounds of the X coordinates of all of 3 defining points. Once you are to > the right of all 3 X coordinates, the winding count is uniformly a single > value over the entire Y range of the (monotonic) quad. > > Consider a quad with a vertical reversal. If one of the endpoints is > higher than the other, then in the area between the Y coordinates of the > endpoints it will increase or decrease the winding count by only 1, and the > sign of that winding count change will be identical to a segment that > connects the two endpoints. For the rest of the quad, the part where it > doubles back on itself, those 2 parts of the path cancel each other out. > You either have a downward portion that curves into an upward portion, or > vice versa. In both cases, that portion has a resulting winding count of 0 > because the direction of those 2 parts of the curve are opposite. > But if the polygon has self intersections, then a line can cross the vertical reversal and its position will depend on the exact curve, so the accumulated winding count will be different along the Y axis. > A cubic is more complicated with more cases to consider, but if you > diagram it out you can see that the winding count contribution off to the > right of the cubic will be identical in all cases to the winding count > contribution of a line segment joining the two endpoints. You can have up > to 3 reversals, but all reversals that are above or below the end points > will be paired with each other and all reversals within the Y range of the > end points will either result in 1 or 3 competing pieces and the 1 or the > majority of the 3 will be in the same direction/sign as the direction/sign > of the segment between the endpoints. If there are 3 then 2 will cancel > out and the remaining one will be the same direction as the endpoint line > segment. > > So, all path segments, regardless of line/quad/cubic that lie entirely to > the left of the clip have identical winding count to a simple line segment. > But that also means that in the EO case, it is not possible to ignore any line segment on the left side ? And with the proper winding count computed, the winding mode has no impact, > the same winding count is appropriate and accurate whether the entire path > is EO or NZ... > I am still skeptical on the winding rules ... will try to study some concrete examples. Thanks again, Laurent -- -- Laurent Bourg?s -------------- next part -------------- An HTML attachment was scrubbed... URL: From bourges.laurent at gmail.com Fri Sep 1 21:09:18 2017 From: bourges.laurent at gmail.com (=?UTF-8?Q?Laurent_Bourg=C3=A8s?=) Date: Fri, 1 Sep 2017 23:09:18 +0200 Subject: [OpenJDK 2D-Dev] RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0 In-Reply-To: References: <342d141a-da55-520b-dae0-c87fbb990a98@oracle.com> <2a2436e3-ac17-f7e3-1088-bd60205cb6e6@oracle.com> <1a80ab24-db5a-9708-e53a-2af277c5bc76@oracle.com> <034d753b-599c-f4c0-f4fa-0a7fa47e76a7@oracle.com> Message-ID: Jim, Here is the current code for my experimental PathClipFilter only to show you what I have done so far: - DMarlingRenderingEngine.getAATileGenerator(): ... // fill shape: final PathIterator pi = norm.getNormalizingPathIterator(rdrCtx, s.getPathIterator(_at)); final int windingRule = pi.getWindingRule(); // note: Winding rule may be EvenOdd ONLY for fill operations ! r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), windingRule); if (windingRule == WIND_NON_ZERO) { DPathConsumer2D pc2d = r; if (rdrCtx.doClip) { pc2d = rdrCtx.transformerPC2D.pathClipper(pc2d); } // TODO: subdivide quad/cubic curves into monotonic curves ? pathTo(rdrCtx, pi, pc2d); } - PathClipper: static final class GeneralPathClipper implements DPathConsumer2D { private DPathConsumer2D out; // Bounds of the drawing region, at pixel precision. private final double[] clipRect; // the outcode of the starting point private int sOutCode = 0; // the current outcode of the current sub path private int cOutCode = 0; GeneralPathClipper(final DRendererContext rdrCtx) { this.clipRect = rdrCtx.clipRect; } GeneralPathClipper init(final DPathConsumer2D out) { this.out = out; // Adjust the clipping rectangle with the renderer offsets final double rdrOffX = DRenderer.RDR_OFFSET_X; final double rdrOffY = DRenderer.RDR_OFFSET_Y; final double[] _clipRect = this.clipRect; _clipRect[0] += rdrOffY; _clipRect[1] += rdrOffY; _clipRect[2] += rdrOffX; _clipRect[3] += rdrOffX; return this; // fluent API } @Override public void pathDone() { out.pathDone(); } @Override public void closePath() { out.closePath(); this.cOutCode = sOutCode; } private void finish() { if (outside) { this.outside = false; out.lineTo(cx0, cy0); } } @Override public void moveTo(final double x0, final double y0) { final int outcode = DHelpers.outcode(x0, y0, clipRect); // basic rejection criteria this.sOutCode = outcode; this.cOutCode = outcode; this.outside = false; out.moveTo(x0, y0); } boolean outside = false; double cx0, cy0; @Override public void lineTo(final double x1, final double y1) { final int outcode0 = this.cOutCode; final int outcode1 = DHelpers.outcode(x1, y1, clipRect); this.cOutCode = outcode1; final int sidecode = (outcode0 & outcode1); // basic rejection criteria: if (sidecode != 0) { // top or bottom or same: if ((outcode0 == outcode1) || ((sidecode & DHelpers.OUTCODE_MASK_T_B) != 0) ) { // corner or cross-boundary this.outside = true; // TODO: add to outside stack (throw if never enter again ?) this.cx0 = x1; this.cy0 = y1; return; } else { // corner or cross-boundary on left or right side: // TODO: add to outside stack (throw if never enter again ?) // line(P0-P1) } } finish(); // clipping disabled: out.lineTo(x1, y1); } @Override public void curveTo(final double x1, final double y1, final double x2, final double y2, final double x3, final double y3) { final int outcode0 = this.cOutCode; final int outcode3 = DHelpers.outcode(x3, y3, clipRect); this.cOutCode = outcode3; // TODO: optimize ? final int outcode1 = DHelpers.outcode(x1, y1, clipRect); final int outcode2 = DHelpers.outcode(x2, y2, clipRect); // basic rejection criteria if ((outcode0 & outcode1 & outcode2 & outcode3) != 0) { // Different quadrant ? if ((outcode0 == outcode3) && (outcode0 == outcode1) && (outcode0 == outcode2)) { // corner or cross-boundary this.outside = true; // TODO: add to outside stack (throw if never enter again ?) this.cx0 = x3; this.cy0 = y3; return; } else { // corner or cross-boundary // TODO: add to outside stack (throw if never enter again ?) // line(P0-P1) finish(); // clipping disabled: out.lineTo(x3, y3); return; } } finish(); // clipping disabled: out.curveTo(x1, y1, x2, y2, x3, y3); } @Override public void quadTo(final double x1, final double y1, final double x2, final double y2) { final int outcode0 = this.cOutCode; final int outcode2 = DHelpers.outcode(x2, y2, clipRect); this.cOutCode = outcode2; // TODO: optimize ? final int outcode1 = DHelpers.outcode(x1, y1, clipRect); // basic rejection criteria if ((outcode0 & outcode1 & outcode2) != 0) { // Different quadrant ? if ((outcode0 == outcode2) && (outcode0 == outcode1)) { // corner or cross-boundary this.outside = true; // TODO: add to outside stack (throw if never enter again ?) this.cx0 = x2; this.cy0 = y2; return; } else { // corner or cross-boundary // TODO: add to outside stack (throw if never enter again ?) // line(P0-P1) finish(); // clipping disabled: out.lineTo(x2, y2); return; } } finish(); // clipping disabled: out.quadTo(x1, y1, x2, y2); } @Override public long getNativeConsumer() { throw new InternalError("Not using a native peer"); } } Here is a screenshot illustrating the remaining paths in Renderer after clipping a 4000x4000 spiral converted as stroked shape: http://cr.openjdk.java.net/~lbourges/png/SpiralTest-dash-false.ser.png You can see all rounds arround the clip that I expect soon to ignore too as I plan to use a corner stack to remember turining points until the path enters again or go back in reverse order... clip off: ~ 145ms clip on: ~ 106ms TODO: handle corner points & turns arround / reverse the clip Cheers, Laurent 2017-09-01 22:09 GMT+02:00 Laurent Bourg?s : > Dear Jim, > > I am not so good at explaining my early solution for NZ rule in english: > - it mimics the Stroker approach > - it skips all intermediate segments outside (except at corners ie > different outcodes) > - preserve only the last point of the entering segment > > So mostly invisible segments on the left and right sides are skipped from > the original that makes the Renderer only processing visible segments like > in the Stroker case where I opened the path. > > It improves the performance as less left / right segments are processed in > addLine(). For now the Renderer accepts all segments and only rejects > top/bottom parts and keeps all left/right edges in its processing: that > costs a lot. > > > I think we are discussing two different things. I thought you were > considering a separate filter for clipping filled only paths. I agree that > the Stroker webrev is still needed for stroked paths. We should also > create one for dashed paths that will clip before dashing. There are > multiple stages at which we can clip to reduce processing. > > > Exactly I also like the pipeline approach that decouples stages into > different parts. > > > I take that case into account. How is a prefilter that excludes those > segments any simpler than the Renderer rejecting them itself? > > Keep in mind that they are already rejected. Renderer.addLine() already > does this. In the case of a polygon, there isn't much code you can reduce > because it goes from the loop that feeds the path in the rendering engine > directly to Renderer.move/lineTo() which goes directly to addLine() which > rejects all of those segments. > > > Not on the left / right side. > Closed subpaths or extra segments can be ignored for NZ rule = only > keeping the path closed properly matters. > > Will send you the current code to illustrate the basic filter asap. > > > In the case of curves, the path is nearly as direct, but first you run a > DDA on it to break it into lines. Simply modifying Renderer.quadTo and > cubicTo to perform quick-rejection would be a very simple change (certainly > simpler than adding a new class to do that) and would reject all of those > curved segments much faster... > > > Agreed, I have done it in the past and can provide the change. > > Laurent > > -- -- Laurent Bourg?s -------------- next part -------------- An HTML attachment was scrubbed... URL: From prahalad.kumar.narayanan at oracle.com Sat Sep 2 11:24:36 2017 From: prahalad.kumar.narayanan at oracle.com (Prahalad Kumar Narayanan) Date: Sat, 2 Sep 2017 04:24:36 -0700 (PDT) Subject: [OpenJDK 2D-Dev] RFR: [10] 8187113: test/javax/imageio/plugins/png/PngCreationTimeTest.java fails Message-ID: Hello Everyone Good day to you. Request your time in reviewing the bug fix for . JDK-8187113 test/javax/imageio/plugins/png/PngCreationTimeTest.java fails Root cause: . The Jtreg test- PngCreationTimeTest.java, requires an input image file (duke.png) . But the image was missed when we checked in the fix for issue- JDK-8164971. Details on Fix: . The missing image file has been added to the webrev. . In addition, the test case has been fortified with defensive null checks to report Exception with meaningful messages. Other Info: . I've tested the updated test case on Win7 and Ubuntu VM and the it passes without any issue. . Since there are no platform dependencies to either the original fix (JDK-8164971) or the current one, I believe, the test should pass on other OS(s) as well. Kindly review the fix at your convenience & share your feedback. Review Link: http://cr.openjdk.java.net/~pnarayanan/8187113/webrev.00/ Thank you for your time Have a good day Prahalad N. From Sergey.Bylokhov at oracle.com Sat Sep 2 21:18:35 2017 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Sat, 2 Sep 2017 14:18:35 -0700 Subject: [OpenJDK 2D-Dev] RFR: [10] 8187113: test/javax/imageio/plugins/png/PngCreationTimeTest.java fails In-Reply-To: References: Message-ID: <2363c5a1-7ac2-4357-779c-88bf3761194f@oracle.com> +1 On 9/2/17 04:24, Prahalad Kumar Narayanan wrote: > Hello Everyone > > Good day to you. > > Request your time in reviewing the bug fix for > . JDK-8187113 test/javax/imageio/plugins/png/PngCreationTimeTest.java fails > > Root cause: > . The Jtreg test- PngCreationTimeTest.java, requires an input image file (duke.png) > . But the image was missed when we checked in the fix for issue- JDK-8164971. > > Details on Fix: > . The missing image file has been added to the webrev. > . In addition, the test case has been fortified with defensive null checks to report Exception with meaningful messages. > > Other Info: > . I've tested the updated test case on Win7 and Ubuntu VM and the it passes without any issue. > . Since there are no platform dependencies to either the original fix (JDK-8164971) or the current one, I believe, the test should pass on other OS(s) as well. > > Kindly review the fix at your convenience & share your feedback. > Review Link: http://cr.openjdk.java.net/~pnarayanan/8187113/webrev.00/ > > Thank you for your time > Have a good day > > Prahalad N. > -- Best regards, Sergey. From Sergey.Bylokhov at oracle.com Sun Sep 3 00:58:06 2017 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Sat, 2 Sep 2017 17:58:06 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 8184219 Fix accessibility of tables in the java.desktop module Message-ID: <7b7b2012-af3a-714b-97a8-225cecd4f7aa@oracle.com> Hello, Please review the fix for jdk10. This is the first step to cleanup these warnings: http://cr.openjdk.java.net/~jjg/doc-report/jdk-by-module/java.desktop/report.html Bug: https://bugs.openjdk.java.net/browse/JDK-8184219 Webrev can be found at: http://cr.openjdk.java.net/~serb/8184219/webrev.00 Specdiff:http://cr.openjdk.java.net/~serb/8184219/specdiff.00/java.desktop-summary.html In this fix most of the "striped" tables in the javadoc of java.desktop module are updated: - New attribute scope="col/"row" was added to all headers. - Optional tags like , were removed. - Most of custom table styles like "style=text-align:center" were removed, so all tables now unified. - In a few places the """ was replaced by ", because " is widely used in our docs anyway. Some unchanged tables will be updated later(html files inside doc-files folder, and some tables which are used for layout). More information about a reason for these changes is in the review request for java.base module: http://mail.openjdk.java.net/pipermail/core-libs-dev/2017-July/048519.html -- Best regards, Sergey. From prasanta.sadhukhan at oracle.com Sun Sep 3 13:51:31 2017 From: prasanta.sadhukhan at oracle.com (Prasanta Sadhukhan) Date: Sun, 3 Sep 2017 19:21:31 +0530 Subject: [OpenJDK 2D-Dev] RFR: [10] 8187113: test/javax/imageio/plugins/png/PngCreationTimeTest.java fails In-Reply-To: References: Message-ID: +1 Regards Prasanta On 9/2/2017 4:54 PM, Prahalad Kumar Narayanan wrote: > Hello Everyone > > Good day to you. > > Request your time in reviewing the bug fix for > . JDK-8187113 test/javax/imageio/plugins/png/PngCreationTimeTest.java fails > > Root cause: > . The Jtreg test- PngCreationTimeTest.java, requires an input image file (duke.png) > . But the image was missed when we checked in the fix for issue- JDK-8164971. > > Details on Fix: > . The missing image file has been added to the webrev. > . In addition, the test case has been fortified with defensive null checks to report Exception with meaningful messages. > > Other Info: > . I've tested the updated test case on Win7 and Ubuntu VM and the it passes without any issue. > . Since there are no platform dependencies to either the original fix (JDK-8164971) or the current one, I believe, the test should pass on other OS(s) as well. > > Kindly review the fix at your convenience & share your feedback. > Review Link: http://cr.openjdk.java.net/~pnarayanan/8187113/webrev.00/ > > Thank you for your time > Have a good day > > Prahalad N. From prahalad.kumar.narayanan at oracle.com Mon Sep 4 02:58:16 2017 From: prahalad.kumar.narayanan at oracle.com (Prahalad Kumar Narayanan) Date: Sun, 3 Sep 2017 19:58:16 -0700 (PDT) Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution In-Reply-To: <655a810c-0c64-5334-2ae9-6fa8a42e8ac6@oracle.com> References: <655a810c-0c64-5334-2ae9-6fa8a42e8ac6@oracle.com> Message-ID: <025aa52d-1087-4c3f-9dc0-42e4baa4ed15@default> Hello Prasanta Thanks for the explanation. Being new to the Printing subsystem, it helped get the context of the problem. As I understand, the problem is due to getDefaultPrinterSetings() returning negative values for defYRes and quality. And the fix evades such negative values with a hardcoded low 300 DPI resolution. I 'm suspecting the bug to be in the code that returns values for default printer settings . Since these values are device specific, I believe, the code might use few platform APIs to query the resolutions on that printer device & return the same. . It's here that default resolutions are not retrieved properly. . So my view is to trace this location & fix the population of default printer settings than a hardcoded DPI resolution. . When a problem has surfaced on one printer, there is possibility for the same to occur on many devices as well. . Besides printers may not be supporting low 300 DPI resolution going forward. I may be wrong in my understanding. You could wait for other's review & follow up. Thank you Have a good day Prahalad N. -----Original Message----- From: Prasanta Sadhukhan Sent: Thursday, August 31, 2017 3:39 PM To: Philip Race; 2d-dev Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution Hi All, Please review a fix for an issue where it a NPE is seen when an attempt is made to print to Brother HL-2240D series printer. It seems when RasterPrinterJob#setAttributes() is called with no PrinterResolution attribute set, it first checks if PrinterResolution category is supported. If it is supported, then it sees if the supplied resolution value is supported. Now, since no PrinterResolution attribute is set, so isSupportedValue() returns false [as "printer resolution attribute" object is null] It then goes to get the default resolution attribute via getDefaultAttributeValue() which calls getDefaultPrinterSettings() and use yRes,Quality from this printer to construct a "PrinterResolution" object. Now, it seems in Brother HL-2240D series printer, it supports 3 resolution [300, 600, HQ 1200] but for all these 3 resolutions, getDefaultPrinterSettings() returns -50 for yRes and Quality. So, as per this code http://hg.openjdk.java.net/jdk10/client/jdk/file/dbb5b171a16b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java#l1189 res < 0 and no PrinterResolution object is instantiated so when RPJ accesses printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI);?? it causes NPE. Proposed fix is to create a default lowly 300 dpi PrinterResolution if, for some reason, yRes and Quality from printer comes out -ve. http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.00/ Regards Prasanta From prasanta.sadhukhan at oracle.com Mon Sep 4 10:07:12 2017 From: prasanta.sadhukhan at oracle.com (Prasanta Sadhukhan) Date: Mon, 4 Sep 2017 15:37:12 +0530 Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution In-Reply-To: <025aa52d-1087-4c3f-9dc0-42e4baa4ed15@default> References: <655a810c-0c64-5334-2ae9-6fa8a42e8ac6@oracle.com> <025aa52d-1087-4c3f-9dc0-42e4baa4ed15@default> Message-ID: <2cdbb171-6a58-641d-5865-891966ce156f@oracle.com> Hi Prahalad, Phil, JDK uses DocumentProperties function [1] to query the printer configuration data in windows. For a RIcoh printer which we (in IDC) use by default, pDevMode->dmFields is initialized to 0x200ff0f, which corresponds to DM_MEDIATYPE? | DM_DUPLEX?? | DM_YRESOLUTION?? | DM_TTOPTION | DM_COLLATE? | DM_COPIES? | DM_DEFAULTSOURCE? | DM_PRINTQUALITY? | DM_COLOR? | DM_PAPERWIDTH? | DM_PAPERLENGTH | DM_PAPERSIZE? | DM_ORIENTATION But, for, Brother printer, pDevMode->dmFields is initialized to 0x1930f which corresponds to DM_FORMNAME? | DM_DUPLEX?? | DM_COLLATE | DM_COPIES? | DM_DEFAULTSOURCE? | DM_PAPERWIDTH? | DM_PAPERLENGTH | DM_PAPERSIZE | DM_ORIENTATION so there is no DM_YRESOLUTION and DM_PRINTQUALITY in dmFields, so even though YRESOLUTION and PRINTQUALITY is populated by :DocumentProperties API, the corresponding indices are not set, resulting in having "GETDEFAULT_ERROR" [-50] in the array for those indices. I have modified my fix to populate the yresolution and printquality indices even though dmFields are not set by :DocumeProperties, provided those fields are not 0. I have retained defaulting to low 300 dpi resolution as there might be a case when AwtPrintControl::getDevmode() fails resulting in returning default values which is -50. Also, in linux, we do the similar http://hg.openjdk.java.net/jdk10/client/jdk/file/70359afda5d0/src/java.desktop/unix/classes/sun/print/IPPPrintService.java#l1565 http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.01/ Regards Prasanta [1] [https://msdn.microsoft.com/en-us/library/windows/desktop/dd183576(v=vs.85).aspx] On 9/4/2017 8:28 AM, Prahalad Kumar Narayanan wrote > Hello Prasanta > > Thanks for the explanation. > Being new to the Printing subsystem, it helped get the context of the problem. > > As I understand, the problem is due to getDefaultPrinterSetings() returning negative values for defYRes and quality. > And the fix evades such negative values with a hardcoded low 300 DPI resolution. > > I 'm suspecting the bug to be in the code that returns values for default printer settings > . Since these values are device specific, I believe, the code might use few platform APIs to query the resolutions on that printer device & return the same. > . It's here that default resolutions are not retrieved properly. > . So my view is to trace this location & fix the population of default printer settings than a hardcoded DPI resolution. > . When a problem has surfaced on one printer, there is possibility for the same to occur on many devices as well. > . Besides printers may not be supporting low 300 DPI resolution going forward. > > I may be wrong in my understanding. You could wait for other's review & follow up. > > Thank you > Have a good day > > Prahalad N. > > -----Original Message----- > From: Prasanta Sadhukhan > Sent: Thursday, August 31, 2017 3:39 PM > To: Philip Race; 2d-dev > Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution > > Hi All, > > Please review a fix for an issue where it a NPE is seen when an attempt is made to print to Brother HL-2240D series printer. > > It seems when RasterPrinterJob#setAttributes() is called with no PrinterResolution attribute set, it first checks if PrinterResolution category is supported. > If it is supported, then it sees if the supplied resolution value is supported. Now, since no PrinterResolution attribute is set, so > isSupportedValue() returns false [as "printer resolution attribute" > object is null] > It then goes to get the default resolution attribute via > getDefaultAttributeValue() which calls getDefaultPrinterSettings() and use yRes,Quality from this printer to construct a "PrinterResolution" > object. > > Now, it seems in Brother HL-2240D series printer, it supports 3 resolution [300, 600, HQ 1200] but for all these 3 resolutions, > getDefaultPrinterSettings() returns -50 for yRes and Quality. > So, as per this code > http://hg.openjdk.java.net/jdk10/client/jdk/file/dbb5b171a16b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java#l1189 > res < 0 and no PrinterResolution object is instantiated so when RPJ accesses printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI);?? it causes NPE. > > Proposed fix is to create a default lowly 300 dpi PrinterResolution if, for some reason, yRes and Quality from printer comes out -ve. > http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.00/ > > Regards > Prasanta From neugens at redhat.com Tue Sep 5 12:39:30 2017 From: neugens at redhat.com (Mario Torre) Date: Tue, 5 Sep 2017 14:39:30 +0200 Subject: [OpenJDK 2D-Dev] Font bug with minimal fonts installed In-Reply-To: References: Message-ID: Any ideas or suggestion? Mario On Thu, Aug 31, 2017 at 1:54 PM, Mario Torre wrote: > I have a weird issue with fonts in RHEL (and that means likely means > all derivative, like CentOS and Oracle Linux), although it appears > that the same issue can be replicated on a Fedora 26. > > The issue is this one, in case you want to see more details: > > https://bugzilla.redhat.com/show_bug.cgi?id=1484079 > > From what I can see, basically in this weird setting with no fonts > installed except the bare minimum required and this STIX font package, > the font subsystem fails to initialise properly. STIX fonts are open > type but are CFF format, so they are skipped during the first round of > initialisation. > > What I can't fully get though is why they are still used by default > when simply asking for a SanSerif font: > > Font font = new Font("SansSerif", Font.PLAIN, 12); > > I can see the font code (in fontpath.c) reading this font information > and then skipping it, at the end it still creates an array with 0 > elements (the native method is created with includeFallbacks true, but > there's no fallback, so the array is 0 length), which causes the > exception in the original report (or some variation of it, but they > are basically all the same): > > Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 > at sun.font.CompositeStrike.getStrikeForSlot(CompositeStrike.java:75) > at sun.font.CompositeStrike.getFontMetrics(CompositeStrike.java:93) > at sun.font.Font2D.getFontMetrics(Font2D.java:415) > at java.awt.Font.defaultLineMetrics(Font.java:2176) > at java.awt.Font.getLineMetrics(Font.java:2283) > at java.awt.font.TextLayout.fastInit(TextLayout.java:598) > at java.awt.font.TextLayout.(TextLayout.java:393) > at TestJava.main(TestJava.java:15) > > I suspect there's an actual bug in this logic and we shouldn't try to > access the font (perhaps in the java side) if fontCount, is 0, but I'm > not entirely sure. > > A quick workaround is to just scan also CFF, it seems correct to me > anyway, although maybe the correct check should go after TrueType and > not after Type1, but I left this Linux specific. > > I would like some comment before I go ahead and create an OpenJDK bug > report, perhaps I'm just confused and I'm looking in the wrong place. > The following patch was taken from a 8u-dev in case you want to try > it, and I suggest using a throwaway VM since uninstalling all the > fonts is guaranteed to mess your setup :) > > There is a full attached test case in the bug report, but I can paste > it in the email if you can't look at the link. > > diff -r e96c4a40fdf9 src/solaris/native/sun/awt/fontpath.c > --- a/src/solaris/native/sun/awt/fontpath.c Wed Aug 23 14:14:49 2017 -0400 > +++ b/src/solaris/native/sun/awt/fontpath.c Thu Aug 24 12:14:41 2017 -0400 > @@ -1239,6 +1239,7 @@ > && (strcmp((char*)fontformat, "TrueType") != 0) > #if defined(__linux__) || defined(_AIX) > && (strcmp((char*)fontformat, "Type 1") != 0) > + && (strcmp((char*)fontformat, "CFF") != 0) > #endif > ) { > continue; > > Cheers, > Mario From philip.race at oracle.com Tue Sep 5 16:25:00 2017 From: philip.race at oracle.com (Phil Race) Date: Tue, 5 Sep 2017 09:25:00 -0700 Subject: [OpenJDK 2D-Dev] jdk10/client forest is FROZEN until JDK 10 repos are consolidated. In-Reply-To: <5952E8F9.7010405@oracle.com> References: <5952E8F9.7010405@oracle.com> Message-ID: <4f45d0d1-4c94-fd65-9620-cfe78857887e@oracle.com> The JDK 10 repo consolidation [1] is about to begin. All the JDK forests need to be frozen to make this happen .. as per this excerpt from the email below //>/We're aiming to have the final pre-consolidation integrations of the />/hs and client forests into JDK 10 master the week of August 28 or />/shortly thereafter. Any work urgently needed to JDK 10 in areas that />/push directly to master should also be pushed the week of August 28. />//>/On or about the week of September 4, JDK 10 master will be marked as />/read-only and after it is marked read-only,/ So it is now 5th September and you should consider the client forest FROZEN (and it may actually be read-only already since a request has been sent to ops to make it so). If you do manage to push something there likely it will be lost anyway and you would need to re-push at later date in the new consolidated forest. It will re-open once the consolidation is completed some time next week. In theory it should take only a day or so but there are implications for "boundary" systems which will take a little longer. Of course you will need to throw away all existing copies and re-clone since the forests will be different. -phil. [1] http://mail.openjdk.java.net/pipermail/jdk10-dev/2017-September/000455.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From bourges.laurent at gmail.com Tue Sep 5 20:41:12 2017 From: bourges.laurent at gmail.com (=?UTF-8?Q?Laurent_Bourg=C3=A8s?=) Date: Tue, 5 Sep 2017 22:41:12 +0200 Subject: [OpenJDK 2D-Dev] RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0 In-Reply-To: References: <342d141a-da55-520b-dae0-c87fbb990a98@oracle.com> <2a2436e3-ac17-f7e3-1088-bd60205cb6e6@oracle.com> <1a80ab24-db5a-9708-e53a-2af277c5bc76@oracle.com> <034d753b-599c-f4c0-f4fa-0a7fa47e76a7@oracle.com> Message-ID: Hi Jim, I made good progress on my PathClipFilter that works now perfectly with many test maps for the NZ rule (EO has artefacts if I enable the filter in that case). Here is the updated code below to illustrate the approach: - use a new IndexStack in (D)Helpers to store only corner indexes (0/1 for Top/Bottom Left, 2/3 for Top/Bottom Right) - when the segment is out, I now check (L/R case) if the segment ends have different outcodes to insert needed corners that can be removed later if a segment does the same in the reverse order (same repeated corner is cancelled out): see IndexStack.push(int) - PathClipFilter: static final class PathClipFilter implements DPathConsumer2D { private DPathConsumer2D out; // Bounds of the drawing region, at pixel precision. private final double[] clipRect; private final double[] corners = new double[8]; private boolean init_corners = false; private final IndexStack stack; // the outcode of the starting point private int sOutCode = 0; // the current outcode of the current sub path private int cOutCode = 0; private boolean outside = false; private double cx0, cy0; PathClipFilter(final DRendererContext rdrCtx) { this.clipRect = rdrCtx.clipRect; this.stack = (rdrCtx.stats != null) ? new IndexStack(rdrCtx, rdrCtx.stats.stat_pcf_idxstack_indices, rdrCtx.stats.hist_pcf_idxstack_indices, rdrCtx.stats.stat_array_pcf_idxstack_indices) : new IndexStack(rdrCtx); } PathClipFilter init(final DPathConsumer2D out) { this.out = out; // Adjust the clipping rectangle with the renderer offsets final double rdrOffX = DRenderer.RDR_OFFSET_X; final double rdrOffY = DRenderer.RDR_OFFSET_Y; // add a small rounding error: final double margin = 1e-3d; final double[] _clipRect = this.clipRect; _clipRect[0] -= margin - rdrOffY; _clipRect[1] += margin + rdrOffY; _clipRect[2] -= margin - rdrOffX; _clipRect[3] += margin + rdrOffX; init_corners = true; return this; // fluent API } /** * Disposes this instance: * clean up before reusing this instance */ void dispose() { stack.dispose(); } @Override public void pathDone() { out.pathDone(); // TODO: fix possible leak if exception happened // Dispose this instance: dispose(); } @Override public void closePath() { if (outside) { this.outside = false; if (sOutCode == 0) { finish(); } else { stack.reset(); } } out.closePath(); this.cOutCode = sOutCode; } private void finish() { if (!stack.isEmpty()) { if (init_corners) { init_corners = false; // Top Left (0): corners[0] = clipRect[2]; corners[1] = clipRect[0]; // Bottom Left (1): corners[2] = clipRect[2]; corners[3] = clipRect[1]; // Top right (2): corners[4] = clipRect[3]; corners[5] = clipRect[0]; // Bottom Right (3): corners[6] = clipRect[3]; corners[7] = clipRect[1]; } stack.pullAll(corners, out); } out.lineTo(cx0, cy0); } @Override public void moveTo(final double x0, final double y0) { final int outcode = DHelpers.outcode(x0, y0, clipRect); this.sOutCode = outcode; this.cOutCode = outcode; this.outside = false; out.moveTo(x0, y0); } @Override public void lineTo(final double xe, final double ye) { final int outcode0 = this.cOutCode; final int outcode1 = DHelpers.outcode(xe, ye, clipRect); this.cOutCode = outcode1; final int sideCode = (outcode0 & outcode1); // basic rejection criteria: if (sideCode != 0) { // keep last point coordinate before entering the clip again: this.outside = true; this.cx0 = xe; this.cy0 = ye; clip(sideCode, outcode0, outcode1); return; } if (outside) { this.outside = false; finish(); } // clipping disabled: out.lineTo(xe, ye); } private void clip(final int sideCode, final int outcode0, final int outcode1) { // corner or cross-boundary on left or right side: if ((outcode0 != outcode1) && ((sideCode & DHelpers.OUTCODE_MASK_T_B) != 0)) { // combine outcodes: final int mergeCode = (outcode0 | outcode1); final int tbCode = mergeCode & DHelpers.OUTCODE_MASK_T_B; final int lrCode = mergeCode & DHelpers.OUTCODE_MASK_L_R; // add corners to outside stack: final int off = (lrCode == DHelpers.OUTCODE_LEFT) ? 0 : 2; switch (tbCode) { case DHelpers.OUTCODE_TOP: stack.push(off); // top return; case DHelpers.OUTCODE_BOTTOM: stack.push(off + 1); // bottom return; default: // both TOP / BOTTOM: if ((outcode0 & DHelpers.OUTCODE_TOP) != 0) { // top to bottom stack.push(off); // top stack.push(off + 1); // bottom } else { // bottom to top stack.push(off + 1); // bottom stack.push(off); // top } } } } @Override public void curveTo(final double x1, final double y1, final double x2, final double y2, final double xe, final double ye) { final int outcode0 = this.cOutCode; final int outcode3 = DHelpers.outcode(xe, ye, clipRect); this.cOutCode = outcode3; int sideCode = outcode0 & outcode3; if (sideCode != 0) { sideCode &= DHelpers.outcode(x1, y1, clipRect); sideCode &= DHelpers.outcode(x2, y2, clipRect); // basic rejection criteria: if (sideCode != 0) { // keep last point coordinate before entering the clip again: this.outside = true; this.cx0 = xe; this.cy0 = ye; clip(sideCode, outcode0, outcode3); return; } } if (outside) { this.outside = false; finish(); } // clipping disabled: out.curveTo(x1, y1, x2, y2, xe, ye); } @Override public void quadTo(final double x1, final double y1, final double xe, final double ye) { final int outcode0 = this.cOutCode; final int outcode2 = DHelpers.outcode(xe, ye, clipRect); this.cOutCode = outcode2; int sideCode = outcode0 & outcode2; if (outcode2 != 0) { sideCode &= DHelpers.outcode(x1, y1, clipRect); // basic rejection criteria: if (sideCode != 0) { // keep last point coordinate before entering the clip again: this.outside = true; this.cx0 = xe; this.cy0 = ye; clip(sideCode, outcode0, outcode2); return; } } if (outside) { this.outside = false; finish(); } // clipping disabled: out.quadTo(x1, y1, xe, ye); } @Override public long getNativeConsumer() { throw new InternalError("Not using a native peer"); } } - DHelpers.IndexStack: // a stack of integer indices static final class IndexStack { // integer capacity = edges count / 4 ~ 1024 private static final int INITIAL_COUNT = INITIAL_EDGES_COUNT >> 2; private int end; private int[] indices; // indices ref (dirty) private final IntArrayCache.Reference indices_ref; // used marks (stats only) private int indicesUseMark; private final StatLong stat_idxstack_indices; private final Histogram hist_idxstack_indices; private final StatLong stat_array_idxstack_indices; IndexStack(final DRendererContext rdrCtx) { this(rdrCtx, null, null, null); } IndexStack(final DRendererContext rdrCtx, final StatLong stat_idxstack_indices, final Histogram hist_idxstack_indices, final StatLong stat_array_idxstack_indices) { indices_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_COUNT); // 4K indices = indices_ref.initial; end = 0; if (DO_STATS) { indicesUseMark = 0; } this.stat_idxstack_indices = stat_idxstack_indices; this.hist_idxstack_indices = hist_idxstack_indices; this.stat_array_idxstack_indices = stat_array_idxstack_indices; } /** * Disposes this PolyStack: * clean up before reusing this instance */ void dispose() { end = 0; if (DO_STATS) { stat_idxstack_indices.add(indicesUseMark); hist_idxstack_indices.add(indicesUseMark); // reset marks indicesUseMark = 0; } // Return arrays: // values is kept dirty indices = indices_ref.putArray(indices); } boolean isEmpty() { return (end == 0); } void reset() { end = 0; } void push(final int v) { // remove redundant values (reverse order): int[] _values = indices; final int nc = end; if (nc != 0) { if (_values[nc - 1] == v) { // remove both duplicated values: end--; return; } } if (_values.length <= nc) { if (DO_STATS) { stat_array_idxstack_indices.add(nc + 1); } indices = _values = indices_ref.widenArray(_values, nc, nc + 1); } _values[end++] = v; if (DO_STATS) { // update used marks: if (end > indicesUseMark) { indicesUseMark = end; } } } void pullAll(final double[] points, final DPathConsumer2D io) { final int nc = end; if (nc == 0) { return; } final int[] _values = indices; for (int i = 0, j; i < nc; i++) { j = _values[i] << 1; io.lineTo(points[j], points[j + 1]); } end = 0; } } Here is a screenshot illustrating the remaining paths in Renderer after > clipping a 4000x4000 spiral converted as stroked shape: > http://cr.openjdk.java.net/~lbourges/png/SpiralTest-dash-false.ser.png > Now all useless rounds are totally discarded from the path sent to the Renderer (removing lots of edges on the left/right sides) > clip off: ~ 145ms > clip on: ~ 106ms > clip on: ~ 68ms for this huge filled spiral ~ 50% faster Could you answer my previous email on EO questions ? How to deal with self intersections or is it possible to skip left segments in the EO case or not ? (I am a bit lost) I need a simple path to test clipping with the EO rule (redudant segments); any idea ? Cheers, Laurent -------------- next part -------------- An HTML attachment was scrubbed... URL: From bourges.laurent at gmail.com Wed Sep 6 08:25:50 2017 From: bourges.laurent at gmail.com (=?UTF-8?Q?Laurent_Bourg=C3=A8s?=) Date: Wed, 6 Sep 2017 10:25:50 +0200 Subject: [OpenJDK 2D-Dev] RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0 In-Reply-To: References: <342d141a-da55-520b-dae0-c87fbb990a98@oracle.com> <2a2436e3-ac17-f7e3-1088-bd60205cb6e6@oracle.com> <1a80ab24-db5a-9708-e53a-2af277c5bc76@oracle.com> <034d753b-599c-f4c0-f4fa-0a7fa47e76a7@oracle.com> Message-ID: Hi all, As Jim is no more available to review & answer my questions on java2d / computer graphics, I need another reviewer on this webrev implementing path clipping in Marlin (huge potential gains). Do you know someone else who can help me in the 2d / prism fields to improve the Marlin renderer even more ? Thanks, Laurent Le 5 sept. 2017 22:41, "Laurent Bourg?s" a ?crit : > Hi Jim, > > I made good progress on my PathClipFilter that works now perfectly with > many test maps for the NZ rule (EO has artefacts if I enable the filter in > that case). > > Here is the updated code below to illustrate the approach: > - use a new IndexStack in (D)Helpers to store only corner indexes (0/1 for > Top/Bottom Left, 2/3 for Top/Bottom Right) > - when the segment is out, I now check (L/R case) if the segment ends have > different outcodes to insert needed corners that can be removed later if a > segment does the same in the reverse order (same repeated corner is > cancelled out): see IndexStack.push(int) > > - PathClipFilter: > > static final class PathClipFilter implements DPathConsumer2D { > > private DPathConsumer2D out; > > // Bounds of the drawing region, at pixel precision. > private final double[] clipRect; > > private final double[] corners = new double[8]; > private boolean init_corners = false; > > private final IndexStack stack; > > // the outcode of the starting point > private int sOutCode = 0; > > // the current outcode of the current sub path > private int cOutCode = 0; > > private boolean outside = false; > private double cx0, cy0; > > PathClipFilter(final DRendererContext rdrCtx) { > this.clipRect = rdrCtx.clipRect; > this.stack = (rdrCtx.stats != null) ? > new IndexStack(rdrCtx, > rdrCtx.stats.stat_pcf_idxstack_indices, > rdrCtx.stats.hist_pcf_idxstack_indices, > rdrCtx.stats.stat_array_pcf_idxstack_indices) > : new IndexStack(rdrCtx); > } > > PathClipFilter init(final DPathConsumer2D out) { > this.out = out; > > // Adjust the clipping rectangle with the renderer offsets > final double rdrOffX = DRenderer.RDR_OFFSET_X; > final double rdrOffY = DRenderer.RDR_OFFSET_Y; > > // add a small rounding error: > final double margin = 1e-3d; > > final double[] _clipRect = this.clipRect; > _clipRect[0] -= margin - rdrOffY; > _clipRect[1] += margin + rdrOffY; > _clipRect[2] -= margin - rdrOffX; > _clipRect[3] += margin + rdrOffX; > > init_corners = true; > > return this; // fluent API > } > > /** > * Disposes this instance: > * clean up before reusing this instance > */ > void dispose() { > stack.dispose(); > } > > @Override > public void pathDone() { > out.pathDone(); > > // TODO: fix possible leak if exception happened > // Dispose this instance: > dispose(); > } > > @Override > public void closePath() { > if (outside) { > this.outside = false; > > if (sOutCode == 0) { > finish(); > } else { > stack.reset(); > } > } > out.closePath(); > this.cOutCode = sOutCode; > } > > private void finish() { > if (!stack.isEmpty()) { > if (init_corners) { > init_corners = false; > // Top Left (0): > corners[0] = clipRect[2]; > corners[1] = clipRect[0]; > // Bottom Left (1): > corners[2] = clipRect[2]; > corners[3] = clipRect[1]; > // Top right (2): > corners[4] = clipRect[3]; > corners[5] = clipRect[0]; > // Bottom Right (3): > corners[6] = clipRect[3]; > corners[7] = clipRect[1]; > } > stack.pullAll(corners, out); > } > out.lineTo(cx0, cy0); > } > > @Override > public void moveTo(final double x0, final double y0) { > final int outcode = DHelpers.outcode(x0, y0, clipRect); > this.sOutCode = outcode; > this.cOutCode = outcode; > this.outside = false; > out.moveTo(x0, y0); > } > > @Override > public void lineTo(final double xe, final double ye) { > final int outcode0 = this.cOutCode; > final int outcode1 = DHelpers.outcode(xe, ye, clipRect); > this.cOutCode = outcode1; > > final int sideCode = (outcode0 & outcode1); > > // basic rejection criteria: > if (sideCode != 0) { > // keep last point coordinate before entering the clip > again: > this.outside = true; > this.cx0 = xe; > this.cy0 = ye; > > clip(sideCode, outcode0, outcode1); > return; > } > if (outside) { > this.outside = false; > finish(); > } > // clipping disabled: > out.lineTo(xe, ye); > } > > private void clip(final int sideCode, > final int outcode0, > final int outcode1) > { > // corner or cross-boundary on left or right side: > if ((outcode0 != outcode1) > && ((sideCode & DHelpers.OUTCODE_MASK_T_B) != 0)) > { > // combine outcodes: > final int mergeCode = (outcode0 | outcode1); > final int tbCode = mergeCode & DHelpers.OUTCODE_MASK_T_B; > final int lrCode = mergeCode & DHelpers.OUTCODE_MASK_L_R; > // add corners to outside stack: > final int off = (lrCode == DHelpers.OUTCODE_LEFT) ? 0 : 2; > > switch (tbCode) { > case DHelpers.OUTCODE_TOP: > stack.push(off); // top > return; > case DHelpers.OUTCODE_BOTTOM: > stack.push(off + 1); // bottom > return; > default: > // both TOP / BOTTOM: > if ((outcode0 & DHelpers.OUTCODE_TOP) != 0) { > // top to bottom > stack.push(off); // top > stack.push(off + 1); // bottom > } else { > // bottom to top > stack.push(off + 1); // bottom > stack.push(off); // top > } > } > } > } > > @Override > public void curveTo(final double x1, final double y1, > final double x2, final double y2, > final double xe, final double ye) > { > final int outcode0 = this.cOutCode; > final int outcode3 = DHelpers.outcode(xe, ye, clipRect); > this.cOutCode = outcode3; > > int sideCode = outcode0 & outcode3; > > if (sideCode != 0) { > sideCode &= DHelpers.outcode(x1, y1, clipRect); > sideCode &= DHelpers.outcode(x2, y2, clipRect); > > // basic rejection criteria: > if (sideCode != 0) { > // keep last point coordinate before entering the clip > again: > this.outside = true; > this.cx0 = xe; > this.cy0 = ye; > > clip(sideCode, outcode0, outcode3); > return; > } > } > if (outside) { > this.outside = false; > finish(); > } > // clipping disabled: > out.curveTo(x1, y1, x2, y2, xe, ye); > } > > @Override > public void quadTo(final double x1, final double y1, > final double xe, final double ye) > { > final int outcode0 = this.cOutCode; > final int outcode2 = DHelpers.outcode(xe, ye, clipRect); > this.cOutCode = outcode2; > > int sideCode = outcode0 & outcode2; > > if (outcode2 != 0) { > sideCode &= DHelpers.outcode(x1, y1, clipRect); > > // basic rejection criteria: > if (sideCode != 0) { > // keep last point coordinate before entering the clip > again: > this.outside = true; > this.cx0 = xe; > this.cy0 = ye; > > clip(sideCode, outcode0, outcode2); > return; > } > } > if (outside) { > this.outside = false; > finish(); > } > // clipping disabled: > out.quadTo(x1, y1, xe, ye); > } > > @Override > public long getNativeConsumer() { > throw new InternalError("Not using a native peer"); > } > } > > - DHelpers.IndexStack: > // a stack of integer indices > static final class IndexStack { > > // integer capacity = edges count / 4 ~ 1024 > private static final int INITIAL_COUNT = INITIAL_EDGES_COUNT >> 2; > > private int end; > private int[] indices; > > // indices ref (dirty) > private final IntArrayCache.Reference indices_ref; > > // used marks (stats only) > private int indicesUseMark; > > private final StatLong stat_idxstack_indices; > private final Histogram hist_idxstack_indices; > private final StatLong stat_array_idxstack_indices; > > IndexStack(final DRendererContext rdrCtx) { > this(rdrCtx, null, null, null); > } > > IndexStack(final DRendererContext rdrCtx, > final StatLong stat_idxstack_indices, > final Histogram hist_idxstack_indices, > final StatLong stat_array_idxstack_indices) > { > indices_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_COUNT); // 4K > indices = indices_ref.initial; > end = 0; > > if (DO_STATS) { > indicesUseMark = 0; > } > this.stat_idxstack_indices = stat_idxstack_indices; > this.hist_idxstack_indices = hist_idxstack_indices; > this.stat_array_idxstack_indices = > stat_array_idxstack_indices; > } > > /** > * Disposes this PolyStack: > * clean up before reusing this instance > */ > void dispose() { > end = 0; > > if (DO_STATS) { > stat_idxstack_indices.add(indicesUseMark); > hist_idxstack_indices.add(indicesUseMark); > > // reset marks > indicesUseMark = 0; > } > > // Return arrays: > // values is kept dirty > indices = indices_ref.putArray(indices); > } > > boolean isEmpty() { > return (end == 0); > } > > void reset() { > end = 0; > } > > void push(final int v) { > // remove redundant values (reverse order): > int[] _values = indices; > final int nc = end; > if (nc != 0) { > if (_values[nc - 1] == v) { > // remove both duplicated values: > end--; > return; > } > } > if (_values.length <= nc) { > if (DO_STATS) { > stat_array_idxstack_indices.add(nc + 1); > } > indices = _values = indices_ref.widenArray(_values, nc, > nc + 1); > } > _values[end++] = v; > > if (DO_STATS) { > // update used marks: > if (end > indicesUseMark) { > indicesUseMark = end; > } > } > } > > void pullAll(final double[] points, final DPathConsumer2D io) { > final int nc = end; > if (nc == 0) { > return; > } > final int[] _values = indices; > > for (int i = 0, j; i < nc; i++) { > j = _values[i] << 1; > io.lineTo(points[j], points[j + 1]); > } > end = 0; > } > } > > > Here is a screenshot illustrating the remaining paths in Renderer after >> clipping a 4000x4000 spiral converted as stroked shape: >> http://cr.openjdk.java.net/~lbourges/png/SpiralTest-dash-false.ser.png >> > > Now all useless rounds are totally discarded from the path sent to the > Renderer (removing lots of edges on the left/right sides) > > >> clip off: ~ 145ms >> clip on: ~ 106ms >> > > clip on: ~ 68ms for this huge filled spiral ~ 50% faster > > > Could you answer my previous email on EO questions ? > How to deal with self intersections or is it possible to skip left > segments in the EO case or not ? > (I am a bit lost) > > I need a simple path to test clipping with the EO rule (redudant > segments); any idea ? > > Cheers, > Laurent > -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevin.rushforth at oracle.com Wed Sep 6 14:22:55 2017 From: kevin.rushforth at oracle.com (Kevin Rushforth) Date: Wed, 06 Sep 2017 07:22:55 -0700 Subject: [OpenJDK 2D-Dev] RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0 In-Reply-To: References: <342d141a-da55-520b-dae0-c87fbb990a98@oracle.com> <2a2436e3-ac17-f7e3-1088-bd60205cb6e6@oracle.com> <1a80ab24-db5a-9708-e53a-2af277c5bc76@oracle.com> <034d753b-599c-f4c0-f4fa-0a7fa47e76a7@oracle.com> Message-ID: <59B004BF.2000105@oracle.com> Hi Laurent, Some combination of Phil, Sergey, and I will take a look at this when we can. Perhaps there might be others on these two lists who could lend a helping hand? -- Kevin Laurent Bourg?s wrote: > Hi all, > > As Jim is no more available to review & answer my questions on java2d / > computer graphics, I need another reviewer on this webrev implementing path > clipping in Marlin (huge potential gains). > > Do you know someone else who can help me in the 2d / prism fields to > improve the Marlin renderer even more ? > > Thanks, > Laurent > > > Le 5 sept. 2017 22:41, "Laurent Bourg?s" a > ?crit : > > >> Hi Jim, >> >> I made good progress on my PathClipFilter that works now perfectly with >> many test maps for the NZ rule (EO has artefacts if I enable the filter in >> that case). >> >> Here is the updated code below to illustrate the approach: >> - use a new IndexStack in (D)Helpers to store only corner indexes (0/1 for >> Top/Bottom Left, 2/3 for Top/Bottom Right) >> - when the segment is out, I now check (L/R case) if the segment ends have >> different outcodes to insert needed corners that can be removed later if a >> segment does the same in the reverse order (same repeated corner is >> cancelled out): see IndexStack.push(int) >> >> - PathClipFilter: >> >> static final class PathClipFilter implements DPathConsumer2D { >> >> private DPathConsumer2D out; >> >> // Bounds of the drawing region, at pixel precision. >> private final double[] clipRect; >> >> private final double[] corners = new double[8]; >> private boolean init_corners = false; >> >> private final IndexStack stack; >> >> // the outcode of the starting point >> private int sOutCode = 0; >> >> // the current outcode of the current sub path >> private int cOutCode = 0; >> >> private boolean outside = false; >> private double cx0, cy0; >> >> PathClipFilter(final DRendererContext rdrCtx) { >> this.clipRect = rdrCtx.clipRect; >> this.stack = (rdrCtx.stats != null) ? >> new IndexStack(rdrCtx, >> rdrCtx.stats.stat_pcf_idxstack_indices, >> rdrCtx.stats.hist_pcf_idxstack_indices, >> rdrCtx.stats.stat_array_pcf_idxstack_indices) >> : new IndexStack(rdrCtx); >> } >> >> PathClipFilter init(final DPathConsumer2D out) { >> this.out = out; >> >> // Adjust the clipping rectangle with the renderer offsets >> final double rdrOffX = DRenderer.RDR_OFFSET_X; >> final double rdrOffY = DRenderer.RDR_OFFSET_Y; >> >> // add a small rounding error: >> final double margin = 1e-3d; >> >> final double[] _clipRect = this.clipRect; >> _clipRect[0] -= margin - rdrOffY; >> _clipRect[1] += margin + rdrOffY; >> _clipRect[2] -= margin - rdrOffX; >> _clipRect[3] += margin + rdrOffX; >> >> init_corners = true; >> >> return this; // fluent API >> } >> >> /** >> * Disposes this instance: >> * clean up before reusing this instance >> */ >> void dispose() { >> stack.dispose(); >> } >> >> @Override >> public void pathDone() { >> out.pathDone(); >> >> // TODO: fix possible leak if exception happened >> // Dispose this instance: >> dispose(); >> } >> >> @Override >> public void closePath() { >> if (outside) { >> this.outside = false; >> >> if (sOutCode == 0) { >> finish(); >> } else { >> stack.reset(); >> } >> } >> out.closePath(); >> this.cOutCode = sOutCode; >> } >> >> private void finish() { >> if (!stack.isEmpty()) { >> if (init_corners) { >> init_corners = false; >> // Top Left (0): >> corners[0] = clipRect[2]; >> corners[1] = clipRect[0]; >> // Bottom Left (1): >> corners[2] = clipRect[2]; >> corners[3] = clipRect[1]; >> // Top right (2): >> corners[4] = clipRect[3]; >> corners[5] = clipRect[0]; >> // Bottom Right (3): >> corners[6] = clipRect[3]; >> corners[7] = clipRect[1]; >> } >> stack.pullAll(corners, out); >> } >> out.lineTo(cx0, cy0); >> } >> >> @Override >> public void moveTo(final double x0, final double y0) { >> final int outcode = DHelpers.outcode(x0, y0, clipRect); >> this.sOutCode = outcode; >> this.cOutCode = outcode; >> this.outside = false; >> out.moveTo(x0, y0); >> } >> >> @Override >> public void lineTo(final double xe, final double ye) { >> final int outcode0 = this.cOutCode; >> final int outcode1 = DHelpers.outcode(xe, ye, clipRect); >> this.cOutCode = outcode1; >> >> final int sideCode = (outcode0 & outcode1); >> >> // basic rejection criteria: >> if (sideCode != 0) { >> // keep last point coordinate before entering the clip >> again: >> this.outside = true; >> this.cx0 = xe; >> this.cy0 = ye; >> >> clip(sideCode, outcode0, outcode1); >> return; >> } >> if (outside) { >> this.outside = false; >> finish(); >> } >> // clipping disabled: >> out.lineTo(xe, ye); >> } >> >> private void clip(final int sideCode, >> final int outcode0, >> final int outcode1) >> { >> // corner or cross-boundary on left or right side: >> if ((outcode0 != outcode1) >> && ((sideCode & DHelpers.OUTCODE_MASK_T_B) != 0)) >> { >> // combine outcodes: >> final int mergeCode = (outcode0 | outcode1); >> final int tbCode = mergeCode & DHelpers.OUTCODE_MASK_T_B; >> final int lrCode = mergeCode & DHelpers.OUTCODE_MASK_L_R; >> // add corners to outside stack: >> final int off = (lrCode == DHelpers.OUTCODE_LEFT) ? 0 : 2; >> >> switch (tbCode) { >> case DHelpers.OUTCODE_TOP: >> stack.push(off); // top >> return; >> case DHelpers.OUTCODE_BOTTOM: >> stack.push(off + 1); // bottom >> return; >> default: >> // both TOP / BOTTOM: >> if ((outcode0 & DHelpers.OUTCODE_TOP) != 0) { >> // top to bottom >> stack.push(off); // top >> stack.push(off + 1); // bottom >> } else { >> // bottom to top >> stack.push(off + 1); // bottom >> stack.push(off); // top >> } >> } >> } >> } >> >> @Override >> public void curveTo(final double x1, final double y1, >> final double x2, final double y2, >> final double xe, final double ye) >> { >> final int outcode0 = this.cOutCode; >> final int outcode3 = DHelpers.outcode(xe, ye, clipRect); >> this.cOutCode = outcode3; >> >> int sideCode = outcode0 & outcode3; >> >> if (sideCode != 0) { >> sideCode &= DHelpers.outcode(x1, y1, clipRect); >> sideCode &= DHelpers.outcode(x2, y2, clipRect); >> >> // basic rejection criteria: >> if (sideCode != 0) { >> // keep last point coordinate before entering the clip >> again: >> this.outside = true; >> this.cx0 = xe; >> this.cy0 = ye; >> >> clip(sideCode, outcode0, outcode3); >> return; >> } >> } >> if (outside) { >> this.outside = false; >> finish(); >> } >> // clipping disabled: >> out.curveTo(x1, y1, x2, y2, xe, ye); >> } >> >> @Override >> public void quadTo(final double x1, final double y1, >> final double xe, final double ye) >> { >> final int outcode0 = this.cOutCode; >> final int outcode2 = DHelpers.outcode(xe, ye, clipRect); >> this.cOutCode = outcode2; >> >> int sideCode = outcode0 & outcode2; >> >> if (outcode2 != 0) { >> sideCode &= DHelpers.outcode(x1, y1, clipRect); >> >> // basic rejection criteria: >> if (sideCode != 0) { >> // keep last point coordinate before entering the clip >> again: >> this.outside = true; >> this.cx0 = xe; >> this.cy0 = ye; >> >> clip(sideCode, outcode0, outcode2); >> return; >> } >> } >> if (outside) { >> this.outside = false; >> finish(); >> } >> // clipping disabled: >> out.quadTo(x1, y1, xe, ye); >> } >> >> @Override >> public long getNativeConsumer() { >> throw new InternalError("Not using a native peer"); >> } >> } >> >> - DHelpers.IndexStack: >> // a stack of integer indices >> static final class IndexStack { >> >> // integer capacity = edges count / 4 ~ 1024 >> private static final int INITIAL_COUNT = INITIAL_EDGES_COUNT >> 2; >> >> private int end; >> private int[] indices; >> >> // indices ref (dirty) >> private final IntArrayCache.Reference indices_ref; >> >> // used marks (stats only) >> private int indicesUseMark; >> >> private final StatLong stat_idxstack_indices; >> private final Histogram hist_idxstack_indices; >> private final StatLong stat_array_idxstack_indices; >> >> IndexStack(final DRendererContext rdrCtx) { >> this(rdrCtx, null, null, null); >> } >> >> IndexStack(final DRendererContext rdrCtx, >> final StatLong stat_idxstack_indices, >> final Histogram hist_idxstack_indices, >> final StatLong stat_array_idxstack_indices) >> { >> indices_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_COUNT); // 4K >> indices = indices_ref.initial; >> end = 0; >> >> if (DO_STATS) { >> indicesUseMark = 0; >> } >> this.stat_idxstack_indices = stat_idxstack_indices; >> this.hist_idxstack_indices = hist_idxstack_indices; >> this.stat_array_idxstack_indices = >> stat_array_idxstack_indices; >> } >> >> /** >> * Disposes this PolyStack: >> * clean up before reusing this instance >> */ >> void dispose() { >> end = 0; >> >> if (DO_STATS) { >> stat_idxstack_indices.add(indicesUseMark); >> hist_idxstack_indices.add(indicesUseMark); >> >> // reset marks >> indicesUseMark = 0; >> } >> >> // Return arrays: >> // values is kept dirty >> indices = indices_ref.putArray(indices); >> } >> >> boolean isEmpty() { >> return (end == 0); >> } >> >> void reset() { >> end = 0; >> } >> >> void push(final int v) { >> // remove redundant values (reverse order): >> int[] _values = indices; >> final int nc = end; >> if (nc != 0) { >> if (_values[nc - 1] == v) { >> // remove both duplicated values: >> end--; >> return; >> } >> } >> if (_values.length <= nc) { >> if (DO_STATS) { >> stat_array_idxstack_indices.add(nc + 1); >> } >> indices = _values = indices_ref.widenArray(_values, nc, >> nc + 1); >> } >> _values[end++] = v; >> >> if (DO_STATS) { >> // update used marks: >> if (end > indicesUseMark) { >> indicesUseMark = end; >> } >> } >> } >> >> void pullAll(final double[] points, final DPathConsumer2D io) { >> final int nc = end; >> if (nc == 0) { >> return; >> } >> final int[] _values = indices; >> >> for (int i = 0, j; i < nc; i++) { >> j = _values[i] << 1; >> io.lineTo(points[j], points[j + 1]); >> } >> end = 0; >> } >> } >> >> >> Here is a screenshot illustrating the remaining paths in Renderer after >> >>> clipping a 4000x4000 spiral converted as stroked shape: >>> http://cr.openjdk.java.net/~lbourges/png/SpiralTest-dash-false.ser.png >>> >>> >> Now all useless rounds are totally discarded from the path sent to the >> Renderer (removing lots of edges on the left/right sides) >> >> >> >>> clip off: ~ 145ms >>> clip on: ~ 106ms >>> >>> >> clip on: ~ 68ms for this huge filled spiral ~ 50% faster >> >> >> Could you answer my previous email on EO questions ? >> How to deal with self intersections or is it possible to skip left >> segments in the EO case or not ? >> (I am a bit lost) >> >> I need a simple path to test clipping with the EO rule (redudant >> segments); any idea ? >> >> Cheers, >> Laurent >> >> From bourges.laurent at gmail.com Thu Sep 7 06:52:18 2017 From: bourges.laurent at gmail.com (=?UTF-8?Q?Laurent_Bourg=C3=A8s?=) Date: Thu, 7 Sep 2017 08:52:18 +0200 Subject: [OpenJDK 2D-Dev] RFR JDK-8184429: Path clipper added in Marlin2D & MarlinFX 0.8.0 In-Reply-To: <59B004BF.2000105@oracle.com> References: <342d141a-da55-520b-dae0-c87fbb990a98@oracle.com> <2a2436e3-ac17-f7e3-1088-bd60205cb6e6@oracle.com> <1a80ab24-db5a-9708-e53a-2af277c5bc76@oracle.com> <034d753b-599c-f4c0-f4fa-0a7fa47e76a7@oracle.com> <59B004BF.2000105@oracle.com> Message-ID: Hi Kevin, Ok I propose to withdraw or postpone this review after JavaOne where we will be able to discuss in a face to face meeting about Marlin & MarlinFX changes for JDK10. I hope the 2d / jfx groups have other Graphics Guru to help, as good as Jim Graham. Cheers, Laurent Le 6 sept. 2017 16:23, "Kevin Rushforth" a ?crit : > Hi Laurent, > > Some combination of Phil, Sergey, and I will take a look at this when we > can. Perhaps there might be others on these two lists who could lend a > helping hand? > > -- Kevin > > > Laurent Bourg?s wrote: > >> Hi all, >> >> As Jim is no more available to review & answer my questions on java2d / >> computer graphics, I need another reviewer on this webrev implementing >> path >> clipping in Marlin (huge potential gains). >> >> Do you know someone else who can help me in the 2d / prism fields to >> improve the Marlin renderer even more ? >> >> Thanks, >> Laurent >> >> >> Le 5 sept. 2017 22:41, "Laurent Bourg?s" a >> ?crit : >> >> >> >>> Hi Jim, >>> >>> I made good progress on my PathClipFilter that works now perfectly with >>> many test maps for the NZ rule (EO has artefacts if I enable the filter >>> in >>> that case). >>> >>> Here is the updated code below to illustrate the approach: >>> - use a new IndexStack in (D)Helpers to store only corner indexes (0/1 >>> for >>> Top/Bottom Left, 2/3 for Top/Bottom Right) >>> - when the segment is out, I now check (L/R case) if the segment ends >>> have >>> different outcodes to insert needed corners that can be removed later if >>> a >>> segment does the same in the reverse order (same repeated corner is >>> cancelled out): see IndexStack.push(int) >>> >>> - PathClipFilter: >>> >>> static final class PathClipFilter implements DPathConsumer2D { >>> >>> private DPathConsumer2D out; >>> >>> // Bounds of the drawing region, at pixel precision. >>> private final double[] clipRect; >>> >>> private final double[] corners = new double[8]; >>> private boolean init_corners = false; >>> >>> private final IndexStack stack; >>> >>> // the outcode of the starting point >>> private int sOutCode = 0; >>> >>> // the current outcode of the current sub path >>> private int cOutCode = 0; >>> >>> private boolean outside = false; >>> private double cx0, cy0; >>> >>> PathClipFilter(final DRendererContext rdrCtx) { >>> this.clipRect = rdrCtx.clipRect; >>> this.stack = (rdrCtx.stats != null) ? >>> new IndexStack(rdrCtx, >>> rdrCtx.stats.stat_pcf_idxstack_indices, >>> rdrCtx.stats.hist_pcf_idxstack_indices, >>> rdrCtx.stats.stat_array_pcf_idxstack_indices) >>> : new IndexStack(rdrCtx); >>> } >>> >>> PathClipFilter init(final DPathConsumer2D out) { >>> this.out = out; >>> >>> // Adjust the clipping rectangle with the renderer offsets >>> final double rdrOffX = DRenderer.RDR_OFFSET_X; >>> final double rdrOffY = DRenderer.RDR_OFFSET_Y; >>> >>> // add a small rounding error: >>> final double margin = 1e-3d; >>> >>> final double[] _clipRect = this.clipRect; >>> _clipRect[0] -= margin - rdrOffY; >>> _clipRect[1] += margin + rdrOffY; >>> _clipRect[2] -= margin - rdrOffX; >>> _clipRect[3] += margin + rdrOffX; >>> >>> init_corners = true; >>> >>> return this; // fluent API >>> } >>> >>> /** >>> * Disposes this instance: >>> * clean up before reusing this instance >>> */ >>> void dispose() { >>> stack.dispose(); >>> } >>> >>> @Override >>> public void pathDone() { >>> out.pathDone(); >>> >>> // TODO: fix possible leak if exception happened >>> // Dispose this instance: >>> dispose(); >>> } >>> >>> @Override >>> public void closePath() { >>> if (outside) { >>> this.outside = false; >>> >>> if (sOutCode == 0) { >>> finish(); >>> } else { >>> stack.reset(); >>> } >>> } >>> out.closePath(); >>> this.cOutCode = sOutCode; >>> } >>> >>> private void finish() { >>> if (!stack.isEmpty()) { >>> if (init_corners) { >>> init_corners = false; >>> // Top Left (0): >>> corners[0] = clipRect[2]; >>> corners[1] = clipRect[0]; >>> // Bottom Left (1): >>> corners[2] = clipRect[2]; >>> corners[3] = clipRect[1]; >>> // Top right (2): >>> corners[4] = clipRect[3]; >>> corners[5] = clipRect[0]; >>> // Bottom Right (3): >>> corners[6] = clipRect[3]; >>> corners[7] = clipRect[1]; >>> } >>> stack.pullAll(corners, out); >>> } >>> out.lineTo(cx0, cy0); >>> } >>> >>> @Override >>> public void moveTo(final double x0, final double y0) { >>> final int outcode = DHelpers.outcode(x0, y0, clipRect); >>> this.sOutCode = outcode; >>> this.cOutCode = outcode; >>> this.outside = false; >>> out.moveTo(x0, y0); >>> } >>> >>> @Override >>> public void lineTo(final double xe, final double ye) { >>> final int outcode0 = this.cOutCode; >>> final int outcode1 = DHelpers.outcode(xe, ye, clipRect); >>> this.cOutCode = outcode1; >>> >>> final int sideCode = (outcode0 & outcode1); >>> >>> // basic rejection criteria: >>> if (sideCode != 0) { >>> // keep last point coordinate before entering the clip >>> again: >>> this.outside = true; >>> this.cx0 = xe; >>> this.cy0 = ye; >>> >>> clip(sideCode, outcode0, outcode1); >>> return; >>> } >>> if (outside) { >>> this.outside = false; >>> finish(); >>> } >>> // clipping disabled: >>> out.lineTo(xe, ye); >>> } >>> >>> private void clip(final int sideCode, >>> final int outcode0, >>> final int outcode1) >>> { >>> // corner or cross-boundary on left or right side: >>> if ((outcode0 != outcode1) >>> && ((sideCode & DHelpers.OUTCODE_MASK_T_B) != 0)) >>> { >>> // combine outcodes: >>> final int mergeCode = (outcode0 | outcode1); >>> final int tbCode = mergeCode & DHelpers.OUTCODE_MASK_T_B; >>> final int lrCode = mergeCode & DHelpers.OUTCODE_MASK_L_R; >>> // add corners to outside stack: >>> final int off = (lrCode == DHelpers.OUTCODE_LEFT) ? 0 : >>> 2; >>> >>> switch (tbCode) { >>> case DHelpers.OUTCODE_TOP: >>> stack.push(off); // top >>> return; >>> case DHelpers.OUTCODE_BOTTOM: >>> stack.push(off + 1); // bottom >>> return; >>> default: >>> // both TOP / BOTTOM: >>> if ((outcode0 & DHelpers.OUTCODE_TOP) != 0) { >>> // top to bottom >>> stack.push(off); // top >>> stack.push(off + 1); // bottom >>> } else { >>> // bottom to top >>> stack.push(off + 1); // bottom >>> stack.push(off); // top >>> } >>> } >>> } >>> } >>> >>> @Override >>> public void curveTo(final double x1, final double y1, >>> final double x2, final double y2, >>> final double xe, final double ye) >>> { >>> final int outcode0 = this.cOutCode; >>> final int outcode3 = DHelpers.outcode(xe, ye, clipRect); >>> this.cOutCode = outcode3; >>> >>> int sideCode = outcode0 & outcode3; >>> >>> if (sideCode != 0) { >>> sideCode &= DHelpers.outcode(x1, y1, clipRect); >>> sideCode &= DHelpers.outcode(x2, y2, clipRect); >>> >>> // basic rejection criteria: >>> if (sideCode != 0) { >>> // keep last point coordinate before entering the >>> clip >>> again: >>> this.outside = true; >>> this.cx0 = xe; >>> this.cy0 = ye; >>> >>> clip(sideCode, outcode0, outcode3); >>> return; >>> } >>> } >>> if (outside) { >>> this.outside = false; >>> finish(); >>> } >>> // clipping disabled: >>> out.curveTo(x1, y1, x2, y2, xe, ye); >>> } >>> >>> @Override >>> public void quadTo(final double x1, final double y1, >>> final double xe, final double ye) >>> { >>> final int outcode0 = this.cOutCode; >>> final int outcode2 = DHelpers.outcode(xe, ye, clipRect); >>> this.cOutCode = outcode2; >>> >>> int sideCode = outcode0 & outcode2; >>> >>> if (outcode2 != 0) { >>> sideCode &= DHelpers.outcode(x1, y1, clipRect); >>> >>> // basic rejection criteria: >>> if (sideCode != 0) { >>> // keep last point coordinate before entering the >>> clip >>> again: >>> this.outside = true; >>> this.cx0 = xe; >>> this.cy0 = ye; >>> >>> clip(sideCode, outcode0, outcode2); >>> return; >>> } >>> } >>> if (outside) { >>> this.outside = false; >>> finish(); >>> } >>> // clipping disabled: >>> out.quadTo(x1, y1, xe, ye); >>> } >>> >>> @Override >>> public long getNativeConsumer() { >>> throw new InternalError("Not using a native peer"); >>> } >>> } >>> >>> - DHelpers.IndexStack: >>> // a stack of integer indices >>> static final class IndexStack { >>> >>> // integer capacity = edges count / 4 ~ 1024 >>> private static final int INITIAL_COUNT = INITIAL_EDGES_COUNT >> >>> 2; >>> >>> private int end; >>> private int[] indices; >>> >>> // indices ref (dirty) >>> private final IntArrayCache.Reference indices_ref; >>> >>> // used marks (stats only) >>> private int indicesUseMark; >>> >>> private final StatLong stat_idxstack_indices; >>> private final Histogram hist_idxstack_indices; >>> private final StatLong stat_array_idxstack_indices; >>> >>> IndexStack(final DRendererContext rdrCtx) { >>> this(rdrCtx, null, null, null); >>> } >>> >>> IndexStack(final DRendererContext rdrCtx, >>> final StatLong stat_idxstack_indices, >>> final Histogram hist_idxstack_indices, >>> final StatLong stat_array_idxstack_indices) >>> { >>> indices_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_COUNT); // >>> 4K >>> indices = indices_ref.initial; >>> end = 0; >>> >>> if (DO_STATS) { >>> indicesUseMark = 0; >>> } >>> this.stat_idxstack_indices = stat_idxstack_indices; >>> this.hist_idxstack_indices = hist_idxstack_indices; >>> this.stat_array_idxstack_indices = >>> stat_array_idxstack_indices; >>> } >>> >>> /** >>> * Disposes this PolyStack: >>> * clean up before reusing this instance >>> */ >>> void dispose() { >>> end = 0; >>> >>> if (DO_STATS) { >>> stat_idxstack_indices.add(indicesUseMark); >>> hist_idxstack_indices.add(indicesUseMark); >>> >>> // reset marks >>> indicesUseMark = 0; >>> } >>> >>> // Return arrays: >>> // values is kept dirty >>> indices = indices_ref.putArray(indices); >>> } >>> >>> boolean isEmpty() { >>> return (end == 0); >>> } >>> >>> void reset() { >>> end = 0; >>> } >>> >>> void push(final int v) { >>> // remove redundant values (reverse order): >>> int[] _values = indices; >>> final int nc = end; >>> if (nc != 0) { >>> if (_values[nc - 1] == v) { >>> // remove both duplicated values: >>> end--; >>> return; >>> } >>> } >>> if (_values.length <= nc) { >>> if (DO_STATS) { >>> stat_array_idxstack_indices.add(nc + 1); >>> } >>> indices = _values = indices_ref.widenArray(_values, nc, >>> nc + 1); >>> } >>> _values[end++] = v; >>> >>> if (DO_STATS) { >>> // update used marks: >>> if (end > indicesUseMark) { >>> indicesUseMark = end; >>> } >>> } >>> } >>> >>> void pullAll(final double[] points, final DPathConsumer2D io) { >>> final int nc = end; >>> if (nc == 0) { >>> return; >>> } >>> final int[] _values = indices; >>> >>> for (int i = 0, j; i < nc; i++) { >>> j = _values[i] << 1; >>> io.lineTo(points[j], points[j + 1]); >>> } >>> end = 0; >>> } >>> } >>> >>> >>> Here is a screenshot illustrating the remaining paths in Renderer after >>> >>> >>>> clipping a 4000x4000 spiral converted as stroked shape: >>>> http://cr.openjdk.java.net/~lbourges/png/SpiralTest-dash-false.ser.png >>>> >>>> >>>> >>> Now all useless rounds are totally discarded from the path sent to the >>> Renderer (removing lots of edges on the left/right sides) >>> >>> >>> >>> >>>> clip off: ~ 145ms >>>> clip on: ~ 106ms >>>> >>>> >>>> >>> clip on: ~ 68ms for this huge filled spiral ~ 50% faster >>> >>> >>> Could you answer my previous email on EO questions ? >>> How to deal with self intersections or is it possible to skip left >>> segments in the EO case or not ? >>> (I am a bit lost) >>> >>> I need a simple path to test clipping with the EO rule (redudant >>> segments); any idea ? >>> >>> Cheers, >>> Laurent >>> >>> >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From bourges.laurent at gmail.com Thu Sep 7 08:04:30 2017 From: bourges.laurent at gmail.com (=?UTF-8?Q?Laurent_Bourg=C3=A8s?=) Date: Thu, 7 Sep 2017 10:04:30 +0200 Subject: [OpenJDK 2D-Dev] Client group consolidation ? In-Reply-To: References: Message-ID: Hi, I wonder what is the current status of the Client consolidation gathering former openjdk groups 2d, awt, sound... and maybe openjfx ? I remember that Phil Race proposed such a big change but as these groups are fragmented with only few active members, I think it is worth to merge them to obtain a larger work team. Of course, it depends on the ByLaws consensus. Laurent -------------- next part -------------- An HTML attachment was scrubbed... URL: From Sergey.Bylokhov at oracle.com Fri Sep 8 23:15:34 2017 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Fri, 8 Sep 2017 16:15:34 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 6238123 Typos at Serialized Form javadoc for java.awt.Polygon Message-ID: Hello, Please review the trivial cleanup for jdk10. Bug: https://bugs.openjdk.java.net/browse/JDK-6238123 Webrev can be found at: http://cr.openjdk.java.net/~serb/6238123/webrev.00 -- Best regards, Sergey. From prahalad.kumar.narayanan at oracle.com Sun Sep 10 04:31:35 2017 From: prahalad.kumar.narayanan at oracle.com (Prahalad Kumar Narayanan) Date: Sun, 10 Sep 2017 04:31:35 +0000 (UTC) Subject: [OpenJDK 2D-Dev] [10] Review Request: 6238123 Typos at Serialized Form javadoc for java.awt.Polygon In-Reply-To: References: Message-ID: <6601822b-91fa-4383-beee-8792c9802df2@default> Hello Sergey Your changes fix the Javadoc comments with appropriate usage. +1 Thanks Have a good day Prahalad N. -----Original Message----- From: Sergey Bylokhov Sent: Saturday, September 09, 2017 4:46 AM To: 2d-dev Subject: [OpenJDK 2D-Dev] [10] Review Request: 6238123 Typos at Serialized Form javadoc for java.awt.Polygon Hello, Please review the trivial cleanup for jdk10. Bug: https://bugs.openjdk.java.net/browse/JDK-6238123 Webrev can be found at: http://cr.openjdk.java.net/~serb/6238123/webrev.00 -- Best regards, Sergey. From Sergey.Bylokhov at oracle.com Wed Sep 13 22:39:00 2017 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Wed, 13 Sep 2017 15:39:00 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 8187399 Different problems in the javadoc's links in java.desktop package Message-ID: <8d147726-4e2f-b633-29e5-9ffd7c4cfb54@oracle.com> Hello, Please review the fix for jdk10. Some of the tidy warnings were fixed. Report is here: http://cr.openjdk.java.net/~jjg/doc-report/jdk-by-module/java.desktop/report.html Description: - java/awt/Desktop.java: the links to "developer.apple.com" were removed, it seems that the URLs for these documents are changed over time as well as content. We will mention only "CFBundleDocumentTypes" and "Info.plist" in the description. - javax/print/attribute/standard/PresentationDirection.java: the link was changed from ftp://ftp.pwg.org/pub/pwg/standards/pwg5100.3.pdf to ftp://ftp.pwg.org/pub/pwg/standards/temp_archive/pwg5100.3.pdf , but I guess this is a stable location because the files are there from 2004. - others are just broken links which were fixed. I checked the whole list of links in the desktop module, and found that some of them are broken. For example I cannot find an official place for the tiff specification(and related documents). Also during migration from sun.com we lost some documents, I leave such links as-is, and plan to resurrect the documents somewhere. Bug: https://bugs.openjdk.java.net/browse/JDK-8187399 Webrev can be found at: http://cr.openjdk.java.net/~serb/8187399/webrev.00 -- Best regards, Sergey. From philip.race at oracle.com Fri Sep 15 19:34:58 2017 From: philip.race at oracle.com (Phil Race) Date: Fri, 15 Sep 2017 12:34:58 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 8187399 Different problems in the javadoc's links in java.desktop package In-Reply-To: <8d147726-4e2f-b633-29e5-9ffd7c4cfb54@oracle.com> References: <8d147726-4e2f-b633-29e5-9ffd7c4cfb54@oracle.com> Message-ID: <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> 771 * @implNote Please note that for Mac OS, notifications 772 * are only sent if the Java app is a bundled application, 773 * with a {@code CFBundleDocumentTypes} array present in its 774 * Info.plist. Should we be using {@code ..} for CFBundleDocumentTypes. It is not Java code, but this makes it look like it is. I think we should have some reference to "go see Apple developer docs" to find out what that and Info.plist are .. even if it not a direct link. -phil. On 09/13/2017 03:39 PM, Sergey Bylokhov wrote: > Hello, > Please review the fix for jdk10. > > Some of the tidy warnings were fixed. > Report is here: > http://cr.openjdk.java.net/~jjg/doc-report/jdk-by-module/java.desktop/report.html > > > Description: > - java/awt/Desktop.java: the links to "developer.apple.com" were > removed, it seems that the URLs for these documents are changed over > time as well as content. We will mention only "CFBundleDocumentTypes" > and "Info.plist" in the description. > - javax/print/attribute/standard/PresentationDirection.java: the link > was changed from ftp://ftp.pwg.org/pub/pwg/standards/pwg5100.3.pdf > to ftp://ftp.pwg.org/pub/pwg/standards/temp_archive/pwg5100.3.pdf , > but I guess this is a stable location because the files are there from > 2004. > - others are just broken links which were fixed. > > I checked the whole list of links in the desktop module, and found > that some of them are broken. For example I cannot find an official > place for the tiff specification(and related documents). Also during > migration from sun.com we lost some documents, I leave such links > as-is, and plan to resurrect the documents somewhere. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8187399 > Webrev can be found at: > http://cr.openjdk.java.net/~serb/8187399/webrev.00 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.burkhalter at oracle.com Fri Sep 15 19:40:43 2017 From: brian.burkhalter at oracle.com (Brian Burkhalter) Date: Fri, 15 Sep 2017 12:40:43 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 8187399 Different problems in the javadoc's links in java.desktop package In-Reply-To: <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> References: <8d147726-4e2f-b633-29e5-9ffd7c4cfb54@oracle.com> <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> Message-ID: To be truly picky, the current moniker for ?Apple Unix? is ?macOS? [1]. Brian [1] https://en.wikipedia.org/wiki/MacOS On Sep 15, 2017, at 12:34 PM, Phil Race wrote: > 771 * @implNote Please note that for Mac OS, notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From philip.race at oracle.com Fri Sep 15 19:46:27 2017 From: philip.race at oracle.com (Phil Race) Date: Fri, 15 Sep 2017 12:46:27 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 6238123 Typos at Serialized Form javadoc for java.awt.Polygon In-Reply-To: References: Message-ID: <7ce0edca-b461-f857-b916-9ca16ca7f79f@oracle.com> +1 -phil. On 09/08/2017 04:15 PM, Sergey Bylokhov wrote: > Hello, > Please review the trivial cleanup for jdk10. > > Bug: https://bugs.openjdk.java.net/browse/JDK-6238123 > Webrev can be found at: > http://cr.openjdk.java.net/~serb/6238123/webrev.00 > > From Sergey.Bylokhov at oracle.com Sat Sep 16 01:46:48 2017 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Fri, 15 Sep 2017 18:46:48 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request: 8187399 Different problems in the javadoc's links in java.desktop package In-Reply-To: <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> References: <8d147726-4e2f-b633-29e5-9ffd7c4cfb54@oracle.com> <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> Message-ID: <1b9669d9-80e2-bc6c-b693-4b04c479d3d8@oracle.com> That's of course a stylistic issue, but I think that the keywords(not necessary a java) look better when they are highlighted. Depending from the style it can look like this: http://cr.openjdk.java.net/~serb/8187399/img.png Here is an updated webrev: http://cr.openjdk.java.net/~serb/8187399/webrev.01 - The link to the "Apple Developer Documentation" was added. - Info.plist is also wrapped in the {@code} - Mac OS was replaced by macOS On 9/15/17 12:34, Phil Race wrote: > 771 * @implNote Please note that for Mac OS, notifications > 772 * are only sent if the Java app is a bundled application, > 773 * with a {@code CFBundleDocumentTypes} array present in its > 774 * Info.plist. > > > Should we be using {@code ..} for CFBundleDocumentTypes. It is not Java > code, > but this makes it look like it is. > > I think we should have some reference to "go see Apple developer docs" > to find out what > that and Info.plist are .. even if it not a direct link. > > -phil. > > > On 09/13/2017 03:39 PM, Sergey Bylokhov wrote: >> Hello, >> Please review the fix for jdk10. >> >> Some of the tidy warnings were fixed. >> Report is here: >> http://cr.openjdk.java.net/~jjg/doc-report/jdk-by-module/java.desktop/report.html >> >> >> Description: >> ?- java/awt/Desktop.java: the links to "developer.apple.com" were >> removed, it seems that the URLs for these documents are changed over >> time as well as content. We will mention only "CFBundleDocumentTypes" >> and "Info.plist" in the description. >> ?- javax/print/attribute/standard/PresentationDirection.java: the link >> was changed from ftp://ftp.pwg.org/pub/pwg/standards/pwg5100.3.pdf >> to ftp://ftp.pwg.org/pub/pwg/standards/temp_archive/pwg5100.3.pdf , >> but I guess this is a stable location because the files are there from >> 2004. >> ?- others are just broken links which were fixed. >> >> I checked the whole list of links in the desktop module, and found >> that some of them are broken. For example I cannot find an official >> place for the tiff specification(and related documents). Also during >> migration from sun.com we lost some documents, I leave such links >> as-is, and plan to resurrect the documents somewhere. >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8187399 >> Webrev can be found at: >> http://cr.openjdk.java.net/~serb/8187399/webrev.00 >> >> > -- Best regards, Sergey. From ross at cgl.ucsf.edu Sun Sep 17 21:55:35 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Sun, 17 Sep 2017 14:55:35 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java Message-ID: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> ??? http://phobrain.com/pr/home/gallery/img2112a.jpg Example RGB diff between OpenJDK and Oracle; 673/58903 pixels differ, often by 1, but also like this: 43480c43480 < -9876933 --- > -9942469 43491c43491 < -9876931 --- > -9942467 -------- ??? BufferedImage buffered = ImageIO.read("img2112a.jpg"); ??? try { ??????? PrintStream out = new PrintStream(new File("pixels_2112")); ??????? for (int i=0; i From ross at cgl.ucsf.edu Sun Sep 17 21:59:40 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Sun, 17 Sep 2017 14:59:40 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> Message-ID: <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> Sorry, where are my manners: Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode) Bill On 9/17/17 2:55 PM, Bill Ross wrote: > http://phobrain.com/pr/home/gallery/img2112a.jpg > > Example RGB diff between OpenJDK and Oracle; 673/58903 pixels differ, > often by 1, but also like this: > > 43480c43480 > > < -9876933 > > --- > > > -9942469 > > 43491c43491 > > < -9876931 > > --- > > > -9942467 > > -------- > > ??? BufferedImage buffered = ImageIO.read("img2112a.jpg"); > > ??? try { > ??????? PrintStream out = new PrintStream(new File("pixels_2112")); > ??????? for (int i=0; i ??????????? for (int j=0; j ??????????????? out.println("" + buffered.getRGB(i, j)); > ??????????? } > > ??????? } > ??????? out.close(); > ??? } catch (Exception e) { > ? ? ? ? e.printStackTrace(); > ??? } > > As discovered in BoofCV: > https://groups.google.com/forum/#!topic/boofcv/b40hIlt8Cz0 > > Bigger picture: > > http://phobrain.com/pr/home/poincaredesc.html > > Bill Ross > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ross at cgl.ucsf.edu Sun Sep 17 22:08:30 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Sun, 17 Sep 2017 15:08:30 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> Message-ID: If this is the only diff between the Java's involved here, it is interesting that it is sufficient to switch photo pair distances from Group 2 to Group 3 in the interpretation of the histograms as coordinates in Poincare spherical space. > Bigger picture: http://phobrain.com/pr/home/poincaredesc.html Bill On 9/17/17 2:59 PM, Bill Ross wrote: > > Sorry, where are my manners: > > Java(TM) SE Runtime Environment (build 1.8.0_60-b27) > Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) > > openjdk version "1.8.0_131" > OpenJDK Runtime Environment (build > 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11) > OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode) > > Bill > > > On 9/17/17 2:55 PM, Bill Ross wrote: >> http://phobrain.com/pr/home/gallery/img2112a.jpg >> >> Example RGB diff between OpenJDK and Oracle; 673/58903 pixels differ, >> often by 1, but also like this: >> >> 43480c43480 >> >> < -9876933 >> >> --- >> >> > -9942469 >> >> 43491c43491 >> >> < -9876931 >> >> --- >> >> > -9942467 >> >> -------- >> >> ??? BufferedImage buffered = ImageIO.read("img2112a.jpg"); >> >> ??? try { >> ??????? PrintStream out = new PrintStream(new File("pixels_2112")); >> ??????? for (int i=0; i> ??????????? for (int j=0; j> ??????????????? out.println("" + buffered.getRGB(i, j)); >> ??????????? } >> >> ??????? } >> ??????? out.close(); >> ??? } catch (Exception e) { >> ? ? ? ? e.printStackTrace(); >> ??? } >> >> As discovered in BoofCV: >> https://groups.google.com/forum/#!topic/boofcv/b40hIlt8Cz0 >> >> Bigger picture: >> >> http://phobrain.com/pr/home/poincaredesc.html >> >> Bill Ross >> >> >> >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From philip.race at oracle.com Mon Sep 18 16:15:35 2017 From: philip.race at oracle.com (Phil Race) Date: Mon, 18 Sep 2017 09:15:35 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> Message-ID: Hi, is there a question here ? > If this is the only diff Is that referring to 8u60 vs 8u131 ? FWIW I think the difference that matters is that OpenJDK has different colour profile files, so even though they are processed by the same code the results may be different. I expect the sRGB.pf one is the one that matters. -phil. On 09/17/2017 03:08 PM, Bill Ross wrote: > > If this is the only diff between the Java's involved here, it is > interesting that it is sufficient to switch photo pair distances from > Group 2 to Group 3 in the interpretation of the histograms as > coordinates in Poincare spherical space. > > > Bigger picture: http://phobrain.com/pr/home/poincaredesc.html > > Bill > > On 9/17/17 2:59 PM, Bill Ross wrote: >> >> Sorry, where are my manners: >> >> Java(TM) SE Runtime Environment (build 1.8.0_60-b27) >> Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) >> >> openjdk version "1.8.0_131" >> OpenJDK Runtime Environment (build >> 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11) >> OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode) >> >> Bill >> >> >> On 9/17/17 2:55 PM, Bill Ross wrote: >>> http://phobrain.com/pr/home/gallery/img2112a.jpg >>> >>> Example RGB diff between OpenJDK and Oracle; 673/58903 pixels >>> differ, often by 1, but also like this: >>> >>> 43480c43480 >>> >>> < -9876933 >>> >>> --- >>> >>> > -9942469 >>> >>> 43491c43491 >>> >>> < -9876931 >>> >>> --- >>> >>> > -9942467 >>> >>> -------- >>> >>> BufferedImage buffered = ImageIO.read("img2112a.jpg"); >>> >>> try { >>> PrintStream out = new PrintStream(new File("pixels_2112")); >>> for (int i=0; i>> for (int j=0; j>> out.println("" + buffered.getRGB(i, j)); >>> } >>> >>> } >>> out.close(); >>> } catch (Exception e) { >>> e.printStackTrace(); >>> } >>> >>> As discovered in BoofCV: >>> https://groups.google.com/forum/#!topic/boofcv/b40hIlt8Cz0 >>> >>> Bigger picture: >>> >>> http://phobrain.com/pr/home/poincaredesc.html >>> >>> Bill Ross >>> >>> >>> >>> >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From semyon.sadetsky at oracle.com Mon Sep 18 16:36:16 2017 From: semyon.sadetsky at oracle.com (Semyon Sadetsky) Date: Mon, 18 Sep 2017 09:36:16 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request 8187367: Numerous swing display problems with scaled displays on Windows Message-ID: <050c5fd4-b051-94a8-1b69-89211fe6882a@oracle.com> Hello, Please review fix for JDK10 (in Swing and Java2D): bug: https://bugs.openjdk.java.net/browse/JDK-8187367 webrev: http://cr.openjdk.java.net/~ssadetsky/8187367/webrev.00/ Swing apps may have artifacts on HiDPI screens with fractional scales. There are several issues which may cause various artifacts but the current fix only eliminates one type of artifacts the vertical and horizontal lines on painted surfaces (other issues are addressed by [1] and [2]). This issue was introduced after 8073320 and then incorrectly fixed in 8163193. The root cause is the painter pattern is drawn on a wrongly sized and scaled image in case the image is an off-screen volatile image. The painter doesn't take into account the volatile image inner scale transformation which is not an identity in case of HiDPI , so the resulting image is drawn on of off-screen surface that in the scale times bigger than it is actually necessary. Since such images are cached this was waste of RAM. Also, the bounds sent to the painter class don't take into account the transformation rounding error the latter caused artifacts on the drawing edges. --Semyon [1] https://bugs.openjdk.java.net/browse/JDK-8187585 [2] https://bugs.openjdk.java.net/browse/JDK-8187586 From brian.burkhalter at oracle.com Mon Sep 18 18:55:30 2017 From: brian.burkhalter at oracle.com (Brian Burkhalter) Date: Mon, 18 Sep 2017 11:55:30 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> Message-ID: On Sep 18, 2017, at 9:15 AM, Phil Race wrote: > FWIW I think the difference that matters is that OpenJDK has different colour profile files, > so even though they are processed by the same code the results may be different. > >>> On 9/17/17 2:55 PM, Bill Ross wrote: >>>> out.println("" + buffered.getRGB(i, j)); >>>> To get at the raw pixel data you would want to do for example: int[] iArray = new int[3]; buffered.getData().getPixel(i, j, iArray); Brian -------------- next part -------------- An HTML attachment was scrubbed... URL: From Sergey.Bylokhov at oracle.com Mon Sep 18 19:01:05 2017 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Mon, 18 Sep 2017 12:01:05 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request 8187367: Numerous swing display problems with scaled displays on Windows In-Reply-To: <050c5fd4-b051-94a8-1b69-89211fe6882a@oracle.com> References: <050c5fd4-b051-94a8-1b69-89211fe6882a@oracle.com> Message-ID: <844da46f-a57e-c639-fbaf-5a55ceaaf777@oracle.com> Hi, Semyon. Is it possible to write a test case for this issue? It will be helpful to understand the bug and a fix. On 9/18/17 09:36, Semyon Sadetsky wrote: > Hello, > > Please review fix for JDK10 (in Swing and Java2D): > > bug: https://bugs.openjdk.java.net/browse/JDK-8187367 > > webrev: http://cr.openjdk.java.net/~ssadetsky/8187367/webrev.00/ > > Swing apps? may have artifacts on HiDPI screens with fractional scales. > There are several issues which may cause various artifacts but the > current fix only eliminates one type of artifacts the vertical and > horizontal lines on painted surfaces (other issues are addressed by [1] > and [2]). This issue was introduced after 8073320 and then incorrectly > fixed in 8163193. > > The root cause is the painter pattern is drawn on a wrongly sized and > scaled image in case the image is an off-screen volatile image. The > painter doesn't take into account the volatile image inner scale > transformation which is not an identity in case of HiDPI , so the > resulting image is drawn on of off-screen surface that in the scale > times bigger than it is actually necessary. Since such images are cached > this was waste of RAM. Also, the bounds sent to the painter class don't > take into account the transformation rounding error the latter caused > artifacts on the drawing edges. > > --Semyon > > [1] https://bugs.openjdk.java.net/browse/JDK-8187585 > > [2] https://bugs.openjdk.java.net/browse/JDK-8187586 > -- Best regards, Sergey. From ross at cgl.ucsf.edu Mon Sep 18 19:58:52 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Mon, 18 Sep 2017 12:58:52 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> Message-ID: <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> Thanks! > I expect the sRGB.pf one is the one that matters. Definitely a difference in that file (sizes): 6876? /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/cmm/sRGB.pf 3144? /usr/lib/jvm/java-8-oracle/jre/lib/cmm/sRGB.pf Swapping cmm dirs leads to identical results. Is there any rationale documented/known for choosing one over the other? > Is that referring to 8u60 vs 8u131 ? That's what the version numbers seem to indicate. Bill On 9/18/17 9:15 AM, Phil Race wrote: > Hi, > > is there a question here ? > > > If this is the only diff > > Is that referring to 8u60 vs 8u131 ? > > FWIW I think the difference that matters is that OpenJDK has different > colour profile files, > so even though they are processed by the same code the results may be > different. > > I expect the sRGB.pf one is the one that matters. > > -phil. > > On 09/17/2017 03:08 PM, Bill Ross wrote: >> >> If this is the only diff between the Java's involved here, it is >> interesting that it is sufficient to switch photo pair distances from >> Group 2 to Group 3 in the interpretation of the histograms as >> coordinates in Poincare spherical space. >> >> > Bigger picture: http://phobrain.com/pr/home/poincaredesc.html >> >> Bill >> >> On 9/17/17 2:59 PM, Bill Ross wrote: >>> >>> Sorry, where are my manners: >>> >>> Java(TM) SE Runtime Environment (build 1.8.0_60-b27) >>> Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) >>> >>> openjdk version "1.8.0_131" >>> OpenJDK Runtime Environment (build >>> 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11) >>> OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode) >>> >>> Bill >>> >>> >>> On 9/17/17 2:55 PM, Bill Ross wrote: >>>> http://phobrain.com/pr/home/gallery/img2112a.jpg >>>> >>>> Example RGB diff between OpenJDK and Oracle; 673/58903 pixels >>>> differ, often by 1, but also like this: >>>> >>>> 43480c43480 >>>> >>>> < -9876933 >>>> >>>> --- >>>> >>>> > -9942469 >>>> >>>> 43491c43491 >>>> >>>> < -9876931 >>>> >>>> --- >>>> >>>> > -9942467 >>>> >>>> -------- >>>> >>>> ??? BufferedImage buffered = ImageIO.read("img2112a.jpg"); >>>> >>>> ??? try { >>>> ??????? PrintStream out = new PrintStream(new File("pixels_2112")); >>>> ??????? for (int i=0; i>>> ??????????? for (int j=0; j>>> ??????????????? out.println("" + buffered.getRGB(i, j)); >>>> ??????????? } >>>> >>>> ??????? } >>>> ??????? out.close(); >>>> ??? } catch (Exception e) { >>>> ? ? ? ? e.printStackTrace(); >>>> ??? } >>>> >>>> As discovered in BoofCV: >>>> https://groups.google.com/forum/#!topic/boofcv/b40hIlt8Cz0 >>>> >>>> Bigger picture: >>>> >>>> http://phobrain.com/pr/home/poincaredesc.html >>>> >>>> Bill Ross >>>> >>>> >>>> >>>> >>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ross at cgl.ucsf.edu Mon Sep 18 20:08:27 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Mon, 18 Sep 2017 13:08:27 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> Message-ID: PS - sRGB.pf's being compared here are on Ubuntu, which has 1.8.0.0_144 Oracle on it. Bill On 9/18/17 12:58 PM, Bill Ross wrote: > Thanks! > > > I expect the sRGB.pf one is the one that matters. > > Definitely a difference in that file (sizes): > > 6876? /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/cmm/sRGB.pf > 3144? /usr/lib/jvm/java-8-oracle/jre/lib/cmm/sRGB.pf > > Swapping cmm dirs leads to identical results. > > Is there any rationale documented/known for choosing one over the other? > > > Is that referring to 8u60 vs 8u131 ? > > That's what the version numbers seem to indicate. > > Bill > > On 9/18/17 9:15 AM, Phil Race wrote: >> Hi, >> >> is there a question here ? >> >> > If this is the only diff >> >> Is that referring to 8u60 vs 8u131 ? >> >> FWIW I think the difference that matters is that OpenJDK has >> different colour profile files, >> so even though they are processed by the same code the results may be >> different. >> >> I expect the sRGB.pf one is the one that matters. >> >> -phil. >> >> On 09/17/2017 03:08 PM, Bill Ross wrote: >>> >>> If this is the only diff between the Java's involved here, it is >>> interesting that it is sufficient to switch photo pair distances >>> from Group 2 to Group 3 in the interpretation of the histograms as >>> coordinates in Poincare spherical space. >>> >>> > Bigger picture: http://phobrain.com/pr/home/poincaredesc.html >>> >>> Bill >>> >>> On 9/17/17 2:59 PM, Bill Ross wrote: >>>> >>>> Sorry, where are my manners: >>>> >>>> Java(TM) SE Runtime Environment (build 1.8.0_60-b27) >>>> Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) >>>> >>>> openjdk version "1.8.0_131" >>>> OpenJDK Runtime Environment (build >>>> 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11) >>>> OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode) >>>> >>>> Bill >>>> >>>> >>>> On 9/17/17 2:55 PM, Bill Ross wrote: >>>>> http://phobrain.com/pr/home/gallery/img2112a.jpg >>>>> >>>>> Example RGB diff between OpenJDK and Oracle; 673/58903 pixels >>>>> differ, often by 1, but also like this: >>>>> >>>>> 43480c43480 >>>>> >>>>> < -9876933 >>>>> >>>>> --- >>>>> >>>>> > -9942469 >>>>> >>>>> 43491c43491 >>>>> >>>>> < -9876931 >>>>> >>>>> --- >>>>> >>>>> > -9942467 >>>>> >>>>> -------- >>>>> >>>>> ??? BufferedImage buffered = ImageIO.read("img2112a.jpg"); >>>>> >>>>> ??? try { >>>>> ??????? PrintStream out = new PrintStream(new File("pixels_2112")); >>>>> ??????? for (int i=0; i>>>> ??????????? for (int j=0; j>>>> ??????????????? out.println("" + buffered.getRGB(i, j)); >>>>> ??????????? } >>>>> >>>>> ??????? } >>>>> ??????? out.close(); >>>>> ??? } catch (Exception e) { >>>>> ? ? ? ? e.printStackTrace(); >>>>> ??? } >>>>> >>>>> As discovered in BoofCV: >>>>> https://groups.google.com/forum/#!topic/boofcv/b40hIlt8Cz0 >>>>> >>>>> Bigger picture: >>>>> >>>>> http://phobrain.com/pr/home/poincaredesc.html >>>>> >>>>> Bill Ross >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From philip.race at oracle.com Mon Sep 18 20:09:59 2017 From: philip.race at oracle.com (Phil Race) Date: Mon, 18 Sep 2017 13:09:59 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> Message-ID: <10f89482-6671-e841-6506-7fae5d884ac8@oracle.com> There is no choice for a developer, at least in this scenario, the one that comes with that JDK is the one that will be used. If you mean the choice by the JDK as to which one to ship, then one is compatible with the open source license .. the other is not. -phil. On 9/18/2017 12:58 PM, Bill Ross wrote: > > 6876? /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/cmm/sRGB.pf > 3144? /usr/lib/jvm/java-8-oracle/jre/lib/cmm/sRGB.pf > > Swapping cmm dirs leads to identical results. > > Is there any rationale documented/known for choosing one over the other? From ross at cgl.ucsf.edu Mon Sep 18 21:08:14 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Mon, 18 Sep 2017 14:08:14 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: <10f89482-6671-e841-6506-7fae5d884ac8@oracle.com> References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> <10f89482-6671-e841-6506-7fae5d884ac8@oracle.com> Message-ID: This is for prep of in-house data, so won't be shipped, so I can choose on the basis of quality, if there is a diff. Here's the app:?? http://phobrain.com/pr/home/view.html Bill On 9/18/17 1:09 PM, Phil Race wrote: > There is no choice for a developer, at least in this scenario, > the one that comes with that JDK is the one that will be used. > If you mean the choice by the JDK as to which one to ship, > then one is compatible with the open source license .. the other is not. > > -phil. > > On 9/18/2017 12:58 PM, Bill Ross wrote: >> >> 6876? /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/cmm/sRGB.pf >> 3144? /usr/lib/jvm/java-8-oracle/jre/lib/cmm/sRGB.pf >> >> Swapping cmm dirs leads to identical results. >> >> Is there any rationale documented/known for choosing one over the other? > > From ross at cgl.ucsf.edu Mon Sep 18 21:29:54 2017 From: ross at cgl.ucsf.edu (Bill Ross) Date: Mon, 18 Sep 2017 14:29:54 -0700 Subject: [OpenJDK 2D-Dev] ImageIO.read(jpeg): different RGB from OpenJDK and Oracle Java In-Reply-To: References: <20c0af0f-b61b-7835-be43-66414d757f3e@cgl.ucsf.edu> <61064637-b8dd-5486-340c-f7512a7d181d@cgl.ucsf.edu> <1935fc1d-2036-2266-9381-2f2e94c12a3c@cgl.ucsf.edu> <10f89482-6671-e841-6506-7fae5d884ac8@oracle.com> Message-ID: Re the app: the color mapping option is reached by Phob->Search Mode; the yellow '+' button selects from ~10 color-matching algorithms to match the next pair of pics. Alg used is shown if you hold down mouse in area next to the options. ~7 of the color-match options are histogram-based. Other histogram-based options use the Golden Angle in color space to find pairs; the options are numbers indicating the number of dimensions of each space involved. Bill On 9/18/17 2:08 PM, Bill Ross wrote: > This is for prep of in-house data, so won't be shipped, so I can > choose on the basis of quality, if there is a diff. > > Here's the app:?? http://phobrain.com/pr/home/view.html > > Bill > > > On 9/18/17 1:09 PM, Phil Race wrote: >> There is no choice for a developer, at least in this scenario, >> the one that comes with that JDK is the one that will be used. >> If you mean the choice by the JDK as to which one to ship, >> then one is compatible with the open source license .. the other is not. >> >> -phil. >> >> On 9/18/2017 12:58 PM, Bill Ross wrote: >>> >>> 6876? /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/cmm/sRGB.pf >>> 3144? /usr/lib/jvm/java-8-oracle/jre/lib/cmm/sRGB.pf >>> >>> Swapping cmm dirs leads to identical results. >>> >>> Is there any rationale documented/known for choosing one over the >>> other? >> >> > > From philip.race at oracle.com Mon Sep 18 21:46:30 2017 From: philip.race at oracle.com (Phil Race) Date: Mon, 18 Sep 2017 14:46:30 -0700 Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution In-Reply-To: <2cdbb171-6a58-641d-5865-891966ce156f@oracle.com> References: <655a810c-0c64-5334-2ae9-6fa8a42e8ac6@oracle.com> <025aa52d-1087-4c3f-9dc0-42e4baa4ed15@default> <2cdbb171-6a58-641d-5865-891966ce156f@oracle.com> Message-ID: Hi, On 09/04/2017 03:07 AM, Prasanta Sadhukhan wrote: > Hi Prahalad, Phil, > > JDK uses DocumentProperties function [1] to query the printer > configuration data in windows. > > For a RIcoh printer which we (in IDC) use by default, > pDevMode->dmFields is initialized to 0x200ff0f, which corresponds to > DM_MEDIATYPE | DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION | > DM_COLLATE | DM_COPIES | DM_DEFAULTSOURCE | DM_PRINTQUALITY | > DM_COLOR | DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PAPERSIZE | > DM_ORIENTATION > > But, for, Brother printer, pDevMode->dmFields is initialized to > 0x1930f which corresponds to > DM_FORMNAME | DM_DUPLEX | DM_COLLATE | DM_COPIES | > DM_DEFAULTSOURCE | DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PAPERSIZE | > DM_ORIENTATION > so there is no DM_YRESOLUTION and DM_PRINTQUALITY in dmFields, > so even though YRESOLUTION and PRINTQUALITY is populated by > :DocumentProperties API, the corresponding indices are not set, > resulting in having "GETDEFAULT_ERROR" [-50] in the array for those > indices. > Very odd. It sounds like a driver bug and I'm surprised that the Microsoft HWQL tests don't catch it. Was the driver directly from Brother ? Perhaps someone considered those fields so mandatory that you don't even need to check that they are set ? This case reminds me of the fishy settings for a different bug reviewed here : http://mail.openjdk.java.net/pipermail/2d-dev/2016-June/007011.html so ... I suppose this might be OK but still .. > I have modified my fix to populate the yresolution and printquality > indices even though dmFields are not set by :DocumeProperties, > provided those fields are not 0. Actually the code says you are doing that only if as they are GREATER than zero .. not just different than zero. So here 919 if (pDevMode->dmFields & DM_PRINTQUALITY || pDevMode->dmPrintQuality > 0) { If quality is used by a driver but it forget to set the mask bit then you will still ignore it. Perhaps you want != 0 ? > > I have retained defaulting to low 300 dpi resolution as there might be > a case when AwtPrintControl::getDevmode() fails resulting in returning > default values which is -50. Are you referring to the code in Win32PrintService.java ? I'm not sure about doing that. The way I read your code is now if a driver specifies dmQuality as negative and leaves yRes at zero (meaning ignore it) .. you now no longer ignore it and return a new PrinterResolution for a made up (300,300) resolution. > Also, in linux, we do the similar > http://hg.openjdk.java.net/jdk10/client/jdk/file/70359afda5d0/src/java.desktop/unix/classes/sun/print/IPPPrintService.java#l1565 > What we do in Linux (for Postscript) is different as postscript allows you to specify the DPI for your content and the interpreter must handle that. -phil. > http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.01/ > > Regards > Prasanta > [1] > [https://msdn.microsoft.com/en-us/library/windows/desktop/dd183576(v=vs.85).aspx] > > On 9/4/2017 8:28 AM, Prahalad Kumar Narayanan wrote >> Hello Prasanta >> >> Thanks for the explanation. >> Being new to the Printing subsystem, it helped get the context of the >> problem. >> >> As I understand, the problem is due to getDefaultPrinterSetings() >> returning negative values for defYRes and quality. >> And the fix evades such negative values with a hardcoded low 300 DPI >> resolution. >> >> I 'm suspecting the bug to be in the code that returns values for >> default printer settings >> . Since these values are device specific, I believe, the code might >> use few platform APIs to query the resolutions on that printer device >> & return the same. >> . It's here that default resolutions are not retrieved properly. >> . So my view is to trace this location & fix the population of >> default printer settings than a hardcoded DPI resolution. >> . When a problem has surfaced on one printer, there is >> possibility for the same to occur on many devices as well. >> . Besides printers may not be supporting low 300 DPI resolution >> going forward. >> >> I may be wrong in my understanding. You could wait for other's review >> & follow up. >> >> Thank you >> Have a good day >> >> Prahalad N. >> >> -----Original Message----- >> From: Prasanta Sadhukhan >> Sent: Thursday, August 31, 2017 3:39 PM >> To: Philip Race; 2d-dev >> Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException >> in RasterPrinterJob without PrinterResolution >> >> Hi All, >> >> Please review a fix for an issue where it a NPE is seen when an >> attempt is made to print to Brother HL-2240D series printer. >> >> It seems when RasterPrinterJob#setAttributes() is called with no >> PrinterResolution attribute set, it first checks if PrinterResolution >> category is supported. >> If it is supported, then it sees if the supplied resolution value is >> supported. Now, since no PrinterResolution attribute is set, so >> isSupportedValue() returns false [as "printer resolution attribute" >> object is null] >> It then goes to get the default resolution attribute via >> getDefaultAttributeValue() which calls getDefaultPrinterSettings() >> and use yRes,Quality from this printer to construct a >> "PrinterResolution" >> object. >> >> Now, it seems in Brother HL-2240D series printer, it supports 3 >> resolution [300, 600, HQ 1200] but for all these 3 resolutions, >> getDefaultPrinterSettings() returns -50 for yRes and Quality. >> So, as per this code >> http://hg.openjdk.java.net/jdk10/client/jdk/file/dbb5b171a16b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java#l1189 >> >> res < 0 and no PrinterResolution object is instantiated so when RPJ >> accesses printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI); >> it causes NPE. >> >> Proposed fix is to create a default lowly 300 dpi PrinterResolution >> if, for some reason, yRes and Quality from printer comes out -ve. >> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.00/ >> >> Regards >> Prasanta > -------------- next part -------------- An HTML attachment was scrubbed... URL: From semyon.sadetsky at oracle.com Tue Sep 19 14:58:44 2017 From: semyon.sadetsky at oracle.com (Semyon Sadetsky) Date: Tue, 19 Sep 2017 07:58:44 -0700 Subject: [OpenJDK 2D-Dev] [10] Review Request 8187367: Numerous swing display problems with scaled displays on Windows In-Reply-To: <844da46f-a57e-c639-fbaf-5a55ceaaf777@oracle.com> References: <050c5fd4-b051-94a8-1b69-89211fe6882a@oracle.com> <844da46f-a57e-c639-fbaf-5a55ceaaf777@oracle.com> Message-ID: <170b93d2-abae-1080-2eae-9d0e5c07dcf1@oracle.com> On 09/18/2017 12:01 PM, Sergey Bylokhov wrote: > Hi, Semyon. > Is it possible to write a test case for this issue? It will be helpful > to understand the bug and a fix. Writing the test is hard because those inner interfaces are too deep inside. You can use SwingSet2 demo to see the described artifacts at fractional scales before the fix. > > On 9/18/17 09:36, Semyon Sadetsky wrote: >> Hello, >> >> Please review fix for JDK10 (in Swing and Java2D): >> >> bug: https://bugs.openjdk.java.net/browse/JDK-8187367 >> >> webrev: http://cr.openjdk.java.net/~ssadetsky/8187367/webrev.00/ >> >> Swing apps may have artifacts on HiDPI screens with fractional >> scales. There are several issues which may cause various artifacts >> but the current fix only eliminates one type of artifacts the >> vertical and horizontal lines on painted surfaces (other issues are >> addressed by [1] and [2]). This issue was introduced after 8073320 >> and then incorrectly fixed in 8163193. >> >> The root cause is the painter pattern is drawn on a wrongly sized and >> scaled image in case the image is an off-screen volatile image. The >> painter doesn't take into account the volatile image inner scale >> transformation which is not an identity in case of HiDPI , so the >> resulting image is drawn on of off-screen surface that in the scale >> times bigger than it is actually necessary. Since such images are >> cached this was waste of RAM. Also, the bounds sent to the painter >> class don't take into account the transformation rounding error the >> latter caused artifacts on the drawing edges. >> >> --Semyon >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8187585 >> >> [2] https://bugs.openjdk.java.net/browse/JDK-8187586 >> > > From prasanta.sadhukhan at oracle.com Wed Sep 20 06:29:57 2017 From: prasanta.sadhukhan at oracle.com (Prasanta Sadhukhan) Date: Wed, 20 Sep 2017 11:59:57 +0530 Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution In-Reply-To: References: <655a810c-0c64-5334-2ae9-6fa8a42e8ac6@oracle.com> <025aa52d-1087-4c3f-9dc0-42e4baa4ed15@default> <2cdbb171-6a58-641d-5865-891966ce156f@oracle.com> Message-ID: <67a512e5-a13f-fef0-cf28-bd5e20f7e34f@oracle.com> Hi Phil, On 9/19/2017 3:16 AM, Phil Race wrote: > Hi, > > > On 09/04/2017 03:07 AM, Prasanta Sadhukhan wrote: >> Hi Prahalad, Phil, >> >> JDK uses DocumentProperties function [1] to query the printer >> configuration data in windows. >> >> For a RIcoh printer which we (in IDC) use by default, >> pDevMode->dmFields is initialized to 0x200ff0f, which corresponds to >> DM_MEDIATYPE? | DM_DUPLEX?? | DM_YRESOLUTION?? | DM_TTOPTION | >> DM_COLLATE? | DM_COPIES? | DM_DEFAULTSOURCE? | DM_PRINTQUALITY | >> DM_COLOR? | DM_PAPERWIDTH? | DM_PAPERLENGTH | DM_PAPERSIZE? | >> DM_ORIENTATION >> >> But, for, Brother printer, pDevMode->dmFields is initialized to >> 0x1930f which corresponds to >> DM_FORMNAME? | DM_DUPLEX?? | DM_COLLATE | DM_COPIES? | >> DM_DEFAULTSOURCE? | DM_PAPERWIDTH? | DM_PAPERLENGTH | DM_PAPERSIZE | >> DM_ORIENTATION >> so there is no DM_YRESOLUTION and DM_PRINTQUALITY in dmFields, >> so even though YRESOLUTION and PRINTQUALITY is populated by >> :DocumentProperties API, the corresponding indices are not set, >> resulting in having "GETDEFAULT_ERROR" [-50] in the array for those >> indices. >> > > Very odd. It sounds like a driver bug and I'm surprised that the > Microsoft HWQL tests don't catch it. > Was the driver directly from Brother ? Yes, I took the driver from http://support.brother.com/g/b/downloadlist.aspx?c=us_ot&lang=en&prod=hl2240d_all&os=93 > Perhaps someone considered those fields so mandatory > that you don't even need to check that they are set ? > > This case reminds me of the fishy settings for a different bug > reviewed here : > http://mail.openjdk.java.net/pipermail/2d-dev/2016-June/007011.html so > ... I suppose this might be OK but still .. > >> I have modified my fix to populate the yresolution and printquality >> indices even though dmFields are not set by :DocumeProperties, >> provided those fields are not 0. > > > Actually the code says you are doing that only if as they are GREATER > than zero .. not just different than zero. > > So here > 919 if (pDevMode->dmFields & DM_PRINTQUALITY || > pDevMode->dmPrintQuality > 0) { If quality is used by a driver but it > forget to set the mask bit then you will still ignore it. Perhaps you > want != 0 ? Yes, right. I actually overlooked the spec which says *dmPrintQuality* Specifies the printer resolution. There are four predefined device-independent values: *DMRES_HIGH* *DMRES_MEDIUM* *DMRES_LOW* *DMRES_DRAFT* If a positive value is specified, it specifies the number of dots per inch (DPI) and is therefore device dependent and as per wingdi.h, these values are -ve. I have updated the fix to use !=0. >> >> I have retained defaulting to low 300 dpi resolution as there might >> be a case when AwtPrintControl::getDevmode() fails resulting in >> returning default values which is -50. > > Are you referring to the code in Win32PrintService.java ? > I'm not sure about doing that. The way I read your code is now if a > driver specifies dmQuality as negative > and leaves yRes at zero (meaning ignore it) .. you now no longer > ignore it and return a new PrinterResolution > for a made up (300,300) resolution. > Ok, right. I looked at the spec and saw what you are saying *dmYResolution* Specifies the y-resolution, in dots per inch, of the printer. If the printer initializes this member, the *dmPrintQuality* member specifies the x-resolution which means, if dmPrintQuality is initialized +ve for x resolution, the y-resolution is specified by dmYResolution. Or in reverse way, if dmPrintQuality is -ve, then there might not be any need of specifying dmYResolution. I have updated the webrev to cater to both changes http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.02/ Regards Prasanta >> Also, in linux, we do the similar >> http://hg.openjdk.java.net/jdk10/client/jdk/file/70359afda5d0/src/java.desktop/unix/classes/sun/print/IPPPrintService.java#l1565 >> > What we do in Linux (for Postscript) is different as postscript allows > you to specify the DPI for your content > and the interpreter must handle that. > > -phil. > >> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.01/ >> >> Regards >> Prasanta >> [1] >> [https://msdn.microsoft.com/en-us/library/windows/desktop/dd183576(v=vs.85).aspx] >> >> On 9/4/2017 8:28 AM, Prahalad Kumar Narayanan wrote >>> Hello Prasanta >>> >>> Thanks for the explanation. >>> Being new to the Printing subsystem, it helped get the context of >>> the problem. >>> >>> As I understand, the problem is due to getDefaultPrinterSetings() >>> returning negative values for defYRes and quality. >>> And the fix evades such negative values with a hardcoded low 300 DPI >>> resolution. >>> >>> I 'm suspecting the bug to be in the code that returns values for >>> default printer settings >>> . Since these values are device specific, I believe, the code might >>> use few platform APIs to query the resolutions on that printer >>> device & return the same. >>> . It's here that default resolutions are not retrieved properly. >>> . So my view is to trace this location & fix the population of >>> default printer settings than a hardcoded DPI resolution. >>> ???? . When a problem has surfaced on one printer, there is >>> possibility for the same to occur on many devices as well. >>> ???? . Besides printers may not be supporting low 300 DPI resolution >>> going forward. >>> >>> I may be wrong in my understanding. You could wait for other's >>> review & follow up. >>> >>> Thank you >>> Have a good day >>> >>> Prahalad N. >>> >>> -----Original Message----- >>> From: Prasanta Sadhukhan >>> Sent: Thursday, August 31, 2017 3:39 PM >>> To: Philip Race; 2d-dev >>> Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException >>> in RasterPrinterJob without PrinterResolution >>> >>> Hi All, >>> >>> Please review a fix for an issue where it a NPE is seen when an >>> attempt is made to print to Brother HL-2240D series printer. >>> >>> It seems when RasterPrinterJob#setAttributes() is called with no >>> PrinterResolution attribute set, it first checks if >>> PrinterResolution category is supported. >>> If it is supported, then it sees if the supplied resolution value is >>> supported. Now, since no PrinterResolution attribute is set, so >>> isSupportedValue() returns false [as "printer resolution attribute" >>> object is null] >>> It then goes to get the default resolution attribute via >>> getDefaultAttributeValue() which calls getDefaultPrinterSettings() >>> and use yRes,Quality from this printer to construct a >>> "PrinterResolution" >>> object. >>> >>> Now, it seems in Brother HL-2240D series printer, it supports 3 >>> resolution [300, 600, HQ 1200] but for all these 3 resolutions, >>> getDefaultPrinterSettings() returns -50 for yRes and Quality. >>> So, as per this code >>> http://hg.openjdk.java.net/jdk10/client/jdk/file/dbb5b171a16b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java#l1189 >>> >>> res < 0 and no PrinterResolution object is instantiated so when RPJ >>> accesses >>> printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI); it >>> causes NPE. >>> >>> Proposed fix is to create a default lowly 300 dpi PrinterResolution >>> if, for some reason, yRes and Quality from printer comes out -ve. >>> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.00/ >>> >>> Regards >>> Prasanta >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From philip.race at oracle.com Wed Sep 20 06:47:12 2017 From: philip.race at oracle.com (Philip Race) Date: Tue, 19 Sep 2017 23:47:12 -0700 Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution In-Reply-To: <67a512e5-a13f-fef0-cf28-bd5e20f7e34f@oracle.com> References: <655a810c-0c64-5334-2ae9-6fa8a42e8ac6@oracle.com> <025aa52d-1087-4c3f-9dc0-42e4baa4ed15@default> <2cdbb171-6a58-641d-5865-891966ce156f@oracle.com> <67a512e5-a13f-fef0-cf28-bd5e20f7e34f@oracle.com> Message-ID: <59C20EF0.1060404@oracle.com> Since we are relying on 0 then we need to be sure that the memory starts off as zero so a non-zero value is not random left-over from a previous user of that memory. If I read correctly we allocate this memory using GlobalAlloc in AwtPrintControl::getDevmode and there pass GPTR which should ensure it is zeroed per https://msdn.microsoft.com/en-us/library/windows/desktop/aa366574(v=vs.85).aspx So we should be OK .. and +1 to this version but I find this driver behaviour odd .. -phil. On 9/19/17, 11:29 PM, Prasanta Sadhukhan wrote: > > Hi Phil, > > > On 9/19/2017 3:16 AM, Phil Race wrote: >> Hi, >> >> >> On 09/04/2017 03:07 AM, Prasanta Sadhukhan wrote: >>> Hi Prahalad, Phil, >>> >>> JDK uses DocumentProperties function [1] to query the printer >>> configuration data in windows. >>> >>> For a RIcoh printer which we (in IDC) use by default, >>> pDevMode->dmFields is initialized to 0x200ff0f, which corresponds to >>> DM_MEDIATYPE | DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION | >>> DM_COLLATE | DM_COPIES | DM_DEFAULTSOURCE | DM_PRINTQUALITY | >>> DM_COLOR | DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PAPERSIZE | >>> DM_ORIENTATION >>> >>> But, for, Brother printer, pDevMode->dmFields is initialized to >>> 0x1930f which corresponds to >>> DM_FORMNAME | DM_DUPLEX | DM_COLLATE | DM_COPIES | >>> DM_DEFAULTSOURCE | DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PAPERSIZE | >>> DM_ORIENTATION >>> so there is no DM_YRESOLUTION and DM_PRINTQUALITY in dmFields, >>> so even though YRESOLUTION and PRINTQUALITY is populated by >>> :DocumentProperties API, the corresponding indices are not set, >>> resulting in having "GETDEFAULT_ERROR" [-50] in the array for those >>> indices. >>> >> >> Very odd. It sounds like a driver bug and I'm surprised that the >> Microsoft HWQL tests don't catch it. >> Was the driver directly from Brother ? > Yes, I took the driver from > http://support.brother.com/g/b/downloadlist.aspx?c=us_ot&lang=en&prod=hl2240d_all&os=93 > >> Perhaps someone considered those fields so mandatory >> that you don't even need to check that they are set ? >> >> This case reminds me of the fishy settings for a different bug >> reviewed here : >> http://mail.openjdk.java.net/pipermail/2d-dev/2016-June/007011.html >> so ... I suppose this might be OK but still .. >> >>> I have modified my fix to populate the yresolution and printquality >>> indices even though dmFields are not set by :DocumeProperties, >>> provided those fields are not 0. >> >> >> Actually the code says you are doing that only if as they are GREATER >> than zero .. not just different than zero. >> >> So here >> 919 if (pDevMode->dmFields& DM_PRINTQUALITY || pDevMode->dmPrintQuality> 0) { >> >> If quality is used by a driver but it forget to set the mask bit then you will still ignore it. >> Perhaps you want != 0 ? > Yes, right. I actually overlooked the spec which says > > *dmPrintQuality* > > Specifies the printer resolution. There are four predefined > device-independent values: > > *DMRES_HIGH* > *DMRES_MEDIUM* > *DMRES_LOW* > *DMRES_DRAFT* > > If a positive value is specified, it specifies the number of dots > per inch (DPI) and is therefore device dependent > > and as per wingdi.h, these values are -ve. I have updated the fix to > use !=0. > >> >> >>> >>> I have retained defaulting to low 300 dpi resolution as there might >>> be a case when AwtPrintControl::getDevmode() fails resulting in >>> returning default values which is -50. >> >> Are you referring to the code in Win32PrintService.java ? >> I'm not sure about doing that. The way I read your code is now if a >> driver specifies dmQuality as negative >> and leaves yRes at zero (meaning ignore it) .. you now no longer >> ignore it and return a new PrinterResolution >> for a made up (300,300) resolution. >> > Ok, right. I looked at the spec and saw what you are saying > > *dmYResolution* > > Specifies the y-resolution, in dots per inch, of the printer. If > the printer initializes this member, the *dmPrintQuality* member > specifies the x-resolution > > which means, if dmPrintQuality is initialized +ve for x resolution, > the y-resolution is specified by dmYResolution. > Or in reverse way, if dmPrintQuality is -ve, then there might not be > any need of specifying dmYResolution. > > I have updated the webrev to cater to both changes > > http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.02/ > > Regards > Prasanta > > >>> Also, in linux, we do the similar >>> http://hg.openjdk.java.net/jdk10/client/jdk/file/70359afda5d0/src/java.desktop/unix/classes/sun/print/IPPPrintService.java#l1565 >>> >> What we do in Linux (for Postscript) is different as postscript >> allows you to specify the DPI for your content >> and the interpreter must handle that. >> >> -phil. >> >>> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.01/ >>> >>> Regards >>> Prasanta >>> [1] >>> [https://msdn.microsoft.com/en-us/library/windows/desktop/dd183576(v=vs.85).aspx] >>> >>> On 9/4/2017 8:28 AM, Prahalad Kumar Narayanan wrote >>>> Hello Prasanta >>>> >>>> Thanks for the explanation. >>>> Being new to the Printing subsystem, it helped get the context of >>>> the problem. >>>> >>>> As I understand, the problem is due to getDefaultPrinterSetings() >>>> returning negative values for defYRes and quality. >>>> And the fix evades such negative values with a hardcoded low 300 >>>> DPI resolution. >>>> >>>> I 'm suspecting the bug to be in the code that returns values for >>>> default printer settings >>>> . Since these values are device specific, I believe, the code might >>>> use few platform APIs to query the resolutions on that printer >>>> device & return the same. >>>> . It's here that default resolutions are not retrieved properly. >>>> . So my view is to trace this location & fix the population of >>>> default printer settings than a hardcoded DPI resolution. >>>> . When a problem has surfaced on one printer, there is >>>> possibility for the same to occur on many devices as well. >>>> . Besides printers may not be supporting low 300 DPI >>>> resolution going forward. >>>> >>>> I may be wrong in my understanding. You could wait for other's >>>> review & follow up. >>>> >>>> Thank you >>>> Have a good day >>>> >>>> Prahalad N. >>>> >>>> -----Original Message----- >>>> From: Prasanta Sadhukhan >>>> Sent: Thursday, August 31, 2017 3:39 PM >>>> To: Philip Race; 2d-dev >>>> Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException >>>> in RasterPrinterJob without PrinterResolution >>>> >>>> Hi All, >>>> >>>> Please review a fix for an issue where it a NPE is seen when an >>>> attempt is made to print to Brother HL-2240D series printer. >>>> >>>> It seems when RasterPrinterJob#setAttributes() is called with no >>>> PrinterResolution attribute set, it first checks if >>>> PrinterResolution category is supported. >>>> If it is supported, then it sees if the supplied resolution value >>>> is supported. Now, since no PrinterResolution attribute is set, so >>>> isSupportedValue() returns false [as "printer resolution attribute" >>>> object is null] >>>> It then goes to get the default resolution attribute via >>>> getDefaultAttributeValue() which calls getDefaultPrinterSettings() >>>> and use yRes,Quality from this printer to construct a >>>> "PrinterResolution" >>>> object. >>>> >>>> Now, it seems in Brother HL-2240D series printer, it supports 3 >>>> resolution [300, 600, HQ 1200] but for all these 3 resolutions, >>>> getDefaultPrinterSettings() returns -50 for yRes and Quality. >>>> So, as per this code >>>> http://hg.openjdk.java.net/jdk10/client/jdk/file/dbb5b171a16b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java#l1189 >>>> >>>> res < 0 and no PrinterResolution object is instantiated so when RPJ >>>> accesses >>>> printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI); it >>>> causes NPE. >>>> >>>> Proposed fix is to create a default lowly 300 dpi PrinterResolution >>>> if, for some reason, yRes and Quality from printer comes out -ve. >>>> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.00/ >>>> >>>> Regards >>>> Prasanta >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From neugens at redhat.com Wed Sep 27 13:52:37 2017 From: neugens at redhat.com (Mario Torre) Date: Wed, 27 Sep 2017 15:52:37 +0200 Subject: [OpenJDK 2D-Dev] RFC: Fix for JDK-8188030 Message-ID: Hi all, I would like to propose a fix for https://bugs.openjdk.java.net/browse/JDK-8188030. The issue is basically that CFF fonts are considered better match than Type 1, but are discarded, leaving the font array with no elements. The fix is here: http://cr.openjdk.java.net/~neugens/8188030/webrev.01/ I attached a reproducer to the bug report, but you need a somewhat minimal system setup for that to work. The fix is for OpenJDK 10 at this point, but I plan to backport it all the way down to 7. Any comments? Cheers, Mario From philip.race at oracle.com Wed Sep 27 21:13:49 2017 From: philip.race at oracle.com (Phil Race) Date: Wed, 27 Sep 2017 14:13:49 -0700 Subject: [OpenJDK 2D-Dev] RFC: Fix for JDK-8188030 In-Reply-To: References: Message-ID: This is fine for JDK 9 + 10 but the reason CFF fonts are discarded is that we weren't supporting them properly in Oracle JDK until 9. We should have removed this check in 9 but it was forgotten. If you backport this to 7 and 8 it will be a problem there - for Oracle JDK, not OpenJDK. Although it won't matter for openjdk7 .. since Oracle isn't using that forest any more But it will be an issue for 8. Not sure how to handle that but it should not be backported without a resolution there. -phil. On 09/27/2017 06:52 AM, Mario Torre wrote: > Hi all, > > I would like to propose a fix for > https://bugs.openjdk.java.net/browse/JDK-8188030. > > The issue is basically that CFF fonts are considered better match than > Type 1, but are discarded, leaving the font array with no elements. > > The fix is here: > > http://cr.openjdk.java.net/~neugens/8188030/webrev.01/ > > I attached a reproducer to the bug report, but you need a somewhat > minimal system setup for that to work. > > The fix is for OpenJDK 10 at this point, but I plan to backport it all > the way down to 7. > > Any comments? > > Cheers, > Mario From neugens.limasoftware at gmail.com Thu Sep 28 00:35:20 2017 From: neugens.limasoftware at gmail.com (Mario Torre) Date: Thu, 28 Sep 2017 00:35:20 +0000 Subject: [OpenJDK 2D-Dev] RFC: Fix for JDK-8188030 In-Reply-To: References: Message-ID: Hi Phil, I think I may be fine if we need to live with a local patch in our RPM in 8, this use case should be pretty rare, although I'll check first if there?s some ifdefs that I can use for the backport to 8. I tried to figure out if I could just change the logic but all I could get was NPEs. Perhaps a more fine tuned search to exclude CFF in the first place, but I?m not sure how to craft the query for FontConfig in this case. I?ll push to 10 for now and backport to 9 in the meantime. Do I need another reviewer ok? Cheers, Mario On Wed 27. Sep 2017 at 23:15, Phil Race wrote: > This is fine for JDK 9 + 10 but the reason CFF fonts are discarded > is that we weren't supporting them properly in Oracle JDK until 9. > We should have removed this check in 9 but it was forgotten. > > If you backport this to 7 and 8 it will be a problem there - for > Oracle JDK, not OpenJDK. > > Although it won't matter for openjdk7 .. since Oracle isn't using that > forest any more > > But it will be an issue for 8. Not sure how to handle that but > it should not be backported without a resolution there. > > -phil. > > On 09/27/2017 06:52 AM, Mario Torre wrote: > > Hi all, > > > > I would like to propose a fix for > > https://bugs.openjdk.java.net/browse/JDK-8188030. > > > > The issue is basically that CFF fonts are considered better match than > > Type 1, but are discarded, leaving the font array with no elements. > > > > The fix is here: > > > > http://cr.openjdk.java.net/~neugens/8188030/webrev.01/ > > > > I attached a reproducer to the bug report, but you need a somewhat > > minimal system setup for that to work. > > > > The fix is for OpenJDK 10 at this point, but I plan to backport it all > > the way down to 7. > > > > Any comments? > > > > Cheers, > > Mario > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From philip.race at oracle.com Thu Sep 28 16:23:19 2017 From: philip.race at oracle.com (Philip Race) Date: Thu, 28 Sep 2017 09:23:19 -0700 Subject: [OpenJDK 2D-Dev] RFC: Fix for JDK-8188030 In-Reply-To: References: Message-ID: <59CD21F7.7030801@oracle.com> I think for JDK 8 you can pass down a flag to decide whether to include or exclude CFF. This flag would be the value of FontUtilities.isOpenJDK() and that should tell us what we need. That would preserve the status quo for Oracle JDK and it would be our problem if the same bug were then reported against that release. -phil. On 9/27/17, 5:35 PM, Mario Torre wrote: > Hi Phil, > > I think I may be fine if we need to live with a local patch in our RPM > in 8, this use case should be pretty rare, although I'll check first > if there?s some ifdefs that I can use for the backport to 8. > > I tried to figure out if I could just change the logic but all I could > get was NPEs. > > Perhaps a more fine tuned search to exclude CFF in the first place, > but I?m not sure how to craft the query for FontConfig in this case. > > I?ll push to 10 for now and backport to 9 in the meantime. Do I need > another reviewer ok? > > Cheers, > Mario > > On Wed 27. Sep 2017 at 23:15, Phil Race > wrote: > > This is fine for JDK 9 + 10 but the reason CFF fonts are discarded > is that we weren't supporting them properly in Oracle JDK until 9. > We should have removed this check in 9 but it was forgotten. > > If you backport this to 7 and 8 it will be a problem there - for > Oracle JDK, not OpenJDK. > > Although it won't matter for openjdk7 .. since Oracle isn't using that > forest any more > > But it will be an issue for 8. Not sure how to handle that but > it should not be backported without a resolution there. > > -phil. > > On 09/27/2017 06:52 AM, Mario Torre wrote: > > Hi all, > > > > I would like to propose a fix for > > https://bugs.openjdk.java.net/browse/JDK-8188030. > > > > The issue is basically that CFF fonts are considered better > match than > > Type 1, but are discarded, leaving the font array with no elements. > > > > The fix is here: > > > > http://cr.openjdk.java.net/~neugens/8188030/webrev.01/ > > > > > I attached a reproducer to the bug report, but you need a somewhat > > minimal system setup for that to work. > > > > The fix is for OpenJDK 10 at this point, but I plan to backport > it all > > the way down to 7. > > > > Any comments? > > > > Cheers, > > Mario > -------------- next part -------------- An HTML attachment was scrubbed... URL: From javalists at cbfiddle.com Fri Sep 15 20:08:35 2017 From: javalists at cbfiddle.com (Alan Snyder) Date: Fri, 15 Sep 2017 20:08:35 -0000 Subject: [OpenJDK 2D-Dev] [10] Review Request: 8187399 Different problems in the javadoc's links in java.desktop package In-Reply-To: <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> References: <8d147726-4e2f-b633-29e5-9ffd7c4cfb54@oracle.com> <9ad3322c-3333-555c-6f53-6321eab1435e@oracle.com> Message-ID: <4DDE087A-58D8-4E55-8006-E9A8C92007F6@cbfiddle.com> It?s also not English, which not using @code would make it look like... > On Sep 15, 2017, at 12:34 PM, Phil Race wrote: > > 771 * @implNote Please note that for Mac OS, notifications > 772 * are only sent if the Java app is a bundled application, > 773 * with a {@code CFBundleDocumentTypes} array present in its > 774 * Info.plist. > > Should we be using {@code ..} for CFBundleDocumentTypes. It is not Java code, > but this makes it look like it is. >