bourgesl / marlin-renderer Goto Github PK
View Code? Open in Web Editor NEWMarlin is the FAST Java2D antialiasing rasterizer derived from OpenJDK Pisces (shape)
License: Other
Marlin is the FAST Java2D antialiasing rasterizer derived from OpenJDK Pisces (shape)
License: Other
Latest release generates extra joins when the curve is splitted before the Stroker stage...
Incorrect, useless and maybe slower if measurable !
I will now work on improving my ShapeDumpingGraphics2d to make a more generic RecorderGraphics2d ... and improve the StatsDumpingGraphics2d too in mapbench....
Implementing the blending stage (Java2D) in java instead of C code could benefit from AVX hotspot optimizations...
Later gamma correction could be implemented easily (lookup table ?) or use the new Vector API (from Panama project)
D3D (windows) & OpenGL (macOS) backends are slower with tiles larger than 32x32, however xrender (linux) is faster like the sw pipeline.
Default tile size could be tuned depending on OS:
Use edge slope and subpixel-x error in the pixel coverage precision...
Ideally an image filter (triangle, gaussian, lanzcos) could be used instead of the box filter (subpixel counts) in Renderer
Hi,
I am trying to switch my OpenJDK to use the Marin-renderer. I have downloaded the file marlin-0.9.4.5-Unsafe-OpenJDK11.jar. My OpenJDK version is: 11.0.12.
When I enter the command:
java --patch-module java.desktop=/home/bitnami/geoserver/webapps/geoserver/WEB-INF/lib/marlin-0.9.4.5-Unsafe-OpenJDK11.jar
I get:
The man page for the java command.
Yes, I am probably doing something silly or missing something important due to my being quite the noob. Got to start somewhere I guess.
Can someone please help me understand how to get this working please ?
Filling shapes uses only the Renderer that just upscales initial path elements.
Subdividing curves at dx/dy roots (minima) or at inflexion/cups points (cubic) as done in both Dasher/Stroker should increase curve accuracy.
Hi,
Can you please take a look at the discussion at oracle/visualvm#101 (comment) ? It seems that the Marlin engine is going into some sort of endless loop, causing VisualVM to hang.
I have set up:
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
with https://github.com/bourgesl/marlin-renderer/releases/tag/v0_9_4_5 like this:
JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/a:/opt/marlin/marlin-0.9.4.5-Unsafe.jar"
JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/a:/opt/marlin/marlin-0.9.4.5-Unsafe-sun-java2d.jar"
JAVA_OPTS="$JAVA_OPTS -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine"
and I get:
java.util.ServiceConfigurationError: sun.java2d.pipe.RenderingEngine: Provider sun.java2d.marlin.DMarlinRenderingEngine could not be instantiated
[...]
Caused by: java.lang.NoSuchMethodError: sun.java2d.marlin.MarlinProperties.isDoClip()Z
at sun.java2d.marlin.DMarlinRenderingEngine.<clinit>(DMarlinRenderingEngine.java:56)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
... 47 more
It works fine with for example 0.9.4.1
Did I miss something or is this actually an issue?
Implementing path clipping in Dasher can help ignoring complete path elements.
Take care to handle properly the dash phase in Line (easy length computation) or Curve (curve length computed by subdivision...)
Marlin 7.2.1 says sun.java2d.renderer.doChecks=false when I set value to true.
-Dsun.java2d.renderer.doChecks=true
I have rendering artifacts that I can't debug. (Marlin 7.1, 7.2x)
For example -Dsun.java2d.renderer.useLogger=true works correctly.
I'm trying to solve a problem I have in IntelliJ where anti-aliased fonts with slight (low) hinting show too think font outlines when using a bright-on-dark colour scheme (e.g. white text on blueish background). In black-on-white scheme, the font anti-aliasing is good for me. This makes me think the main issue here is an unsuitable gamma value for the anti-aliasing colours.
Is there a way to tune marlin-renderer to use a different gamma value? Some like (hypothetical)
-Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine
-Dsun.java2d.renderer.gamma=0.8
It seems this settings exists, but the effect is none. For example 0.5:
versus 2.0:
The colours look exactly the same, the font is too thick.
Is there any canvas support of this renderer
like canvas.drawImage(image, x, y); etc.
if so, we could make a game engine based on canvas^_^
Hi,
In the release notes for versions 0.5.5 and 0.5.6 it states:
This release is then recommended for JDK 1.8 only; for JDK 1.7, please use Marlin 0.4.5
But this warning goes away in the notes for versions 0.5.7+.
On the How to Use page it states support for:
OpenJDK 1.7 & 1.8
This is a bit confusing. Does the latest, or any version > 0.4.5, work with a Java 7 runtime?
Fix JavaDoc + setup Nexus keys to upload major releases on maven central (0.7.4, 0.7.5, 0.8.2, 0.9.1)
title says it all...
Ill-conditioned quad or cubic curves can have 1 to 5 curvature maxima... so the current basic approach in Stroker is really approximative for thick curves > 5px ...
In branch better-curves, new adaptative algorithms achieve high quality, but its performance can be improved for general use.
See https://github.com/bourgesl/marlin-renderer/tree/better-curves
EA releases:
https://github.com/bourgesl/marlin-renderer/releases/tag/v1_0_0_EA_3
This is the Marlin-renderer 1.0.0 Early Access release 2 release providing better curve rendering i.e. stroke width along the quad / cubic curves is more accurate.
See screenshots of improvements:
more screenshots: at https://github.com/bourgesl/bourgesl.github.io/tree/master/marlin-better-curves
add new system properties for:
adjust initial arrays accordingly
Detect that edges are all hz or vertical :
That would be a huge win.
Hi,
I've experienced rendering artifacts when I was testing Martin 0.7.0. After enabling checks in Marlin I get following exception. My code draws/fill GlyphVector to g2 from BufferedImage.
FontRenderContext fontRenderContext = new FontRenderContext(new AffineTransform(), true, true);
GlyphVector gv = font.createGlyphVector(fontRenderContext, <text>);
Shape outline = gv.getOutline();
if (symbolizer.getHaloFill() != null && symbolizer.getHaloRadius() > 0.0) {
g2.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(4.0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2.draw(outline);
}
g2.setColor(Color.BLACK);
g2.fill(outline);
java.lang.Throwable
at org.marlin.pisces.IntArrayCache.check(IntArrayCache.java:135)
at org.marlin.pisces.IntArrayCache.fill(IntArrayCache.java:124)
at org.marlin.pisces.Renderer.dispose(Renderer.java:672)
at org.marlin.pisces.MarlinRenderingEngine.getAATileGenerator(MarlinRenderingEngine.java:724)
at sun.java2d.pipe.AAShapePipe.renderPath(AAShapePipe.java:152)
at sun.java2d.pipe.AAShapePipe.fill(AAShapePipe.java:68)
at sun.java2d.pipe.PixelToParallelogramConverter.fill(PixelToParallelogramConverter.java:164)
at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2527)
WARNING: Invalid array value at 2048
...
java.lang.Throwable
at org.marlin.pisces.IntArrayCache.check(IntArrayCache.java:135)
at org.marlin.pisces.IntArrayCache.fill(IntArrayCache.java:124)
at org.marlin.pisces.Renderer.dispose(Renderer.java:672)
at org.marlin.pisces.MarlinRenderingEngine.getAATileGenerator(MarlinRenderingEngine.java:724)
at sun.java2d.pipe.AAShapePipe.renderPath(AAShapePipe.java:152)
at sun.java2d.pipe.AAShapePipe.draw(AAShapePipe.java:64)
at sun.java2d.pipe.PixelToParallelogramConverter.draw(PixelToParallelogramConverter.java:148)
at sun.java2d.SunGraphics2D.draw(SunGraphics2D.java:2497)
INFO: ===============================================================================
INFO: Marlin software rasterizer = ENABLED
INFO: Version = [marlin-0.7.0-Unsafe]
INFO: sun.java2d.renderer = org.marlin.pisces.MarlinRenderingEngine
INFO: sun.java2d.renderer.useThreadLocal = true
INFO: sun.java2d.renderer.useRef = soft
INFO: sun.java2d.renderer.pixelsize = 2048
INFO: sun.java2d.renderer.subPixel_log2_X = 3
INFO: sun.java2d.renderer.subPixel_log2_Y = 3
INFO: sun.java2d.renderer.tileSize_log2 = 5
INFO: sun.java2d.renderer.useSimplifier = false
INFO: sun.java2d.renderer.doStats = false
INFO: sun.java2d.renderer.doMonitors = false
INFO: sun.java2d.renderer.doChecks = true
INFO: sun.java2d.renderer.useLogger = false
INFO: sun.java2d.renderer.logCreateContext = false
INFO: sun.java2d.renderer.logUnsafeMalloc = false
INFO: Renderer settings:
INFO: CUB_COUNT_LG = 2
INFO: CUB_DEC_BND = 20.0
INFO: CUB_INC_BND = 8.0
INFO: QUAD_DEC_BND = 8.0
INFO: sun.java2d.renderer.gamma = 1.0
INFO: ===============================================================================
Todo: put screenshots of artefacts and compare with paper.js framework
Quality hint could help tuning Marlin quality settings at runtime...
Curve accuracy for example ~ 10% perf gain
In some case, offsetted curve may have a loop because solving the 2nd degree equation is not stable in Stroker.computeOffsetCubic().
Using twice the solution in computeOffsetQuad() based on segment intersection, is a good enough approach to make offsets stable
Use the accumulated (kahan) sum algorithm to fix numerical error propagation in both Dasher & Renderer (length, dda)
Instead of using TL or CLQ in single-threaded mode, use one static RenderingContext instance protected by an AtomicBoolean barrier
it should be more efficient (less overhead) ... to be tested
Asap
I'd llike to propose to make this method static...
PathIterator getNormalizingPathIterator(final RendererContext rdrCtx,
final NormMode mode,
final PathIterator src)
...as I do not see any reason not to be static already.
Also I would recommend to replace the implementation by simply...
return mode.getNormalizingPathIterator(rdrCtx, src)
...as (in theory) this shorter code will get inlined while a rather complex switch won't.
Use shared caches but introduce a new CachedArrayReference to simplify the api but provide robustness
Marlin 0.8 provides path clipping optimization that works in Stroker (graphics.draw) and a new PathClipFilter to hanle graphics.fill() operations.
The latter only works properly with the Non zero winding rule.
This issue consists in fixing any problem in the PathClipFilter with the Even/Odd winding rule (used a lot by geoserver) and providing a new automated test to compare polygon filling with/without clipping enabled.
For JDK-9, Marlin releases could be also provided as module patches !
This issue consists in adapting maven build to support JDK-9, travis CI and build JDK-9 jar files (including module-info or multi-release jars ?) based on the latest openjdk branch (jdk-9 or 10)
MarlinFX provides nonAA Marlin renderers that can be backported into Marlin to replace native java2d renderers (C) that suffers from 2 problems:
Goal: replace java2d native renderer ie remove this C code in favor to Marlin !
Tried the latest 0.9.2 with Intellij and I get the following error.
Caused by: java.lang.NoSuchFieldError: refList
at sun.java2d.d3d.D3DRenderQueue.flushBuffer(D3DRenderQueue.java:157)
at sun.java2d.d3d.D3DRenderQueue.flushAndInvokeNow(D3DRenderQueue.java:142)
at sun.java2d.d3d.D3DRenderQueue.getInstance(D3DRenderQueue.java:53)
at sun.java2d.d3d.D3DGraphicsDevice.getDeviceCaps(D3DGraphicsDevice.java:108)
at sun.java2d.d3d.D3DGraphicsDevice.createDevice(D3DGraphicsDevice.java:87)
at sun.awt.Win32GraphicsEnvironment.makeScreenDevice(Win32GraphicsEnvironment.java:235)
at sun.java2d.SunGraphicsEnvironment.getScreenDevices(SunGraphicsEnvironment.java:181)
at sun.awt.Win32GraphicsEnvironment.getDefaultScreenDevice(Win32GraphicsEnvironment.java:118)
at java.awt.Window.initGC(Window.java:476)
If I switch back to 0.9.1 there are not issues.
Intellij settings relevant to Marlin-render
-Xbootclasspath/a:C:\Programs\marlin\marlin-0.9.2-Unsafe.jar
-Xbootclasspath/p:C:\Programs\marlin\marlin-0.9.2-Unsafe-sun-java2d.jar
sun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine
sun.java2d.renderer.subPixel_log2_X=8
sun.java2d.renderer.subPixel_log2_Y=5
sun.java2d.renderer.tileSize_log2=7
sun.java2d.renderer.tileWidth_log2=6
sun.java2d.renderer.useSimplifier=true
Build and execute the following class using OpenJDK8 with marlin-0.9.3-Unsafe.jar:
EndlessLoop.java.txt
I used the following OpenJDK variant on OpenSUSE Leap 42.3:
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (IcedTea 3.9.0) (build 1.8.0_181-b13 suse-27.1-x86_64)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
It hangs forever consuming 100% CPU in line 29: g2.draw(line)
Changing line 27
Line2D line = new Line2D.Double(10, 10, 0, 4e7);
to a smaller value like
Line2D line = new Line2D.Double(10, 10, 0, 1e7);
does not block and reaches line 30 within a second.
I notice the tag is on commit 28fecc0 from master - was it built from the wrong branch also?
Brief description:
When I was using JFreeChart library to draw a chart, but the chart overlay occurs. According to my investigation, it looks like a graphics issue of JDK or Marlin Renderer (the Graphics2D.fill(Shape) doesn't clear the BufferedImage).
Details:
On one of our application page, there are two charts, one is thumbnail chart with a vernier, the other is line chart. User drags the vernier then the line chart will be redrawn. After user drags dozens of times the line chart overlay occurs, the previous paint is not cleared. I ran the same test on different Zulu versions and got different test results. For the details, please refer to the attachments.
Environment:
OS: Linux version 4.4.0-73-generic (builder@buildfarm) (gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4) ) #0 SMP Thu Jan 1 00:00:00 UTC 2015
VGA compatible controller: Intel Corporation ValleyView Gen7 (rev 11)
JFreeChart lib: 0.9.9
BugDetails.zip
Last Nov 12 2019, Vladimir Yaroslavskiy integrated the long-awaited DPQS 2019 patch into OpenJDK14.
Since Marlin release 0.9.4, it contains previous DPQS code (2019.5), so it is time to upgrade.
Use a new profile=speed|quality system property to easily set other internal settings to tune marlin for performance or quality
HiDPI screens are 4K or larger.
Tuning Marlin settings in this case can improve slightly performance by adjusting pixel sizes (X/Y) accordingly (initial arrays instead of array caches)
We have a PDF here that contains a form with graphs with very thin lines. When rendered with ICEpdf with Oracle JDK 8 (Ductus), the graphs are rendered correctly. With OpenJDK 8 (Pisces), the graphs are only rendered when we zoom in to about 600%. With Marlin, the graphs show up at 150% zoom factor.
The issue can be worked around in ICEpdf by setting
-Dorg.icepdf.core.strokeAdjustmentEnabled=true -Dorg.icepdf.core.strokeAdjustmentThreshold=1f -Dorg.icepdf.core.strokeAdjustmentValue=1f
As far as I understand, this will basically force a minimum line with of 1. With Pisces and this workaround however the graphs disappear again when zooming out below 70%.
And of course, the lines are thicker than they are supposed to be.
Debugging MarlinRenderingEngine, execution steps into line 208:
widthScale = (float)Math.sqrt(at.getDeterminant());
In our scenario, at.getDeterminant() returns the value -0.47389273965262657 and widthScale and thus the value returned by userSpaceLineWidth(AffineTransform, float) is NaN.
Using the absolute value of at.getDeterminant(), the lines seem to get rendered correctly, the value returned by userSpaceLineWidth(AffineTransform, float) then is 0.18158083 - but I have no idea if this is a correct solution :-)
Sorry I have not been able to reproduce the issue like it is done here: https://bugs.openjdk.java.net/browse/JDK-6829673
But I'll attach the PDF that reproduces the problem with ICEpdf Viewer: https://www.icesoft.org/wiki/display/PDF/Viewer+RI
GraphsWithThinLines.pdf
Please let me know if I can provide more infos or help with testing etc.
Cheers,
Torsten
TexturePaint fills could be optimized in java2d pipeline:
The exception is thrown in line number 59 of OffHeapArray.java:
UNSAFE = Unsafe.getUnsafe();
This call is supposed to throw a SecurityException, that is why the Unsafe instance is obtained reflectively a few lines earlier:
Unsafe ref = null;
try {
final Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
ref = (Unsafe) field.get(null);
} catch (Exception e) {
MarlinUtils.logInfo("Unable to get sun.misc.Unsafe; exit now.");
System.exit(1);
}
The value of ref
should be assigned to UNSAFE
, like in previous Marlin versions.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.