├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
├── rasterPerf.log
├── results
└── integration-tests.log
└── src
├── main
├── java
│ ├── com
│ │ └── sun
│ │ │ ├── javafx
│ │ │ ├── geom
│ │ │ │ └── Path2D.java
│ │ │ └── sg
│ │ │ │ └── prism
│ │ │ │ ├── NGCanvas.java
│ │ │ │ └── NGCanvasPath.java
│ │ │ ├── marlin
│ │ │ ├── ArrayCacheConst.java
│ │ │ ├── ByteArrayCache.java
│ │ │ ├── CollinearSimplifier.java
│ │ │ ├── Curve.java
│ │ │ ├── DCollinearSimplifier.java
│ │ │ ├── DCurve.java
│ │ │ ├── DDasher.java
│ │ │ ├── DHelpers.java
│ │ │ ├── DMarlinRenderer.java
│ │ │ ├── DMarlinRenderingEngine.java
│ │ │ ├── DPathConsumer2D.java
│ │ │ ├── DPathSimplifier.java
│ │ │ ├── DRenderer.java
│ │ │ ├── DRendererContext.java
│ │ │ ├── DRendererNoAA.java
│ │ │ ├── DStroker.java
│ │ │ ├── DTransformingPathConsumer2D.java
│ │ │ ├── Dasher.java
│ │ │ ├── DoubleArrayCache.java
│ │ │ ├── FloatArrayCache.java
│ │ │ ├── FloatMath.java
│ │ │ ├── Helpers.java
│ │ │ ├── IntArrayCache.java
│ │ │ ├── MarlinAlphaConsumer.java
│ │ │ ├── MarlinConst.java
│ │ │ ├── MarlinProperties.java
│ │ │ ├── MarlinRenderer.java
│ │ │ ├── MarlinRenderingEngine.java
│ │ │ ├── MarlinUtils.java
│ │ │ ├── MaskMarlinAlphaConsumer.java
│ │ │ ├── MergeSort.java
│ │ │ ├── OffHeapArray.java
│ │ │ ├── PathSimplifier.java
│ │ │ ├── Renderer.java
│ │ │ ├── RendererContext.java
│ │ │ ├── RendererNoAA.java
│ │ │ ├── RendererStats.java
│ │ │ ├── Stroker.java
│ │ │ ├── TransformingPathConsumer2D.java
│ │ │ ├── Version.java
│ │ │ ├── conv.sh
│ │ │ ├── makeIntFloatClasses.sh
│ │ │ └── stats
│ │ │ │ ├── Histogram.java
│ │ │ │ ├── Monitor.java
│ │ │ │ └── StatLong.java
│ │ │ ├── prism
│ │ │ ├── BasicStroke.java
│ │ │ └── impl
│ │ │ │ ├── ps
│ │ │ │ └── CachingShapeRep.java
│ │ │ │ └── shape
│ │ │ │ ├── DMarlinPrismUtils.java
│ │ │ │ ├── DMarlinRasterizer.java
│ │ │ │ ├── MarlinPrismUtils.java
│ │ │ │ ├── MarlinRasterizer.java
│ │ │ │ └── ShapeUtil.java
│ │ │ └── util
│ │ │ └── reentrant
│ │ │ ├── ReentrantContext.java
│ │ │ ├── ReentrantContextProvider.java
│ │ │ ├── ReentrantContextProviderCLQ.java
│ │ │ └── ReentrantContextProviderTL.java
│ └── test
│ │ ├── BigLeftSide.java
│ │ ├── PathApp.java
│ │ ├── PathBug.java
│ │ ├── PolygonClipTest.java
│ │ ├── PolygonTest.java
│ │ ├── PolylineClipTest.java
│ │ ├── PolylineWideClipTest.java
│ │ ├── RasterPerf.java
│ │ ├── ShapeOutlineBug.java
│ │ ├── ShapeOutlineBugCirclePath.java
│ │ ├── ShapeOutlineBugRectangle.java
│ │ ├── ShapePerformanceBug.java
│ │ ├── TestNonAARasterization.java
│ │ ├── TextTest.java
│ │ ├── TrianglePerformanceTest.java
│ │ └── WebViewTest.java
└── resources
│ └── com
│ └── sun
│ └── marlin
│ └── Version.properties
└── test
├── java
└── test
│ ├── com
│ └── sun
│ │ ├── javafx
│ │ └── geom
│ │ │ └── Path2DGrowTest.java
│ │ └── marlin
│ │ ├── ClipShapeTest.java
│ │ ├── DashedRectTest.java
│ │ ├── QPathTest.java
│ │ └── ScaleClipTest.java
│ └── util
│ └── Util.java
└── resources
├── GUIMark 2 - HTML5 Vector Test.html
├── GUIMark 2 - HTML5 Vector Test_fichiers
└── ga.js
└── logging.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | /*.sh
2 | /*.png
3 | dependency-reduced-pom.xml
4 | /target/
5 | nbactions.xml
6 | nb-configuration.xml
7 | nbactions-deployer.xml
8 | /nbproject/
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MarlinFX renderer
2 | =================
3 |
4 | MarlinFX is the JavaFX port of the [Marlin-renderer](https://github.com/bourgesl/marlin-renderer) (scanline rasterizer only) aimed to be faster than Open/Native Pisces.
5 |
6 | Release history
7 | ===============
8 |
9 | Latest release: https://github.com/bourgesl/marlin-fx/releases/latest
10 |
11 | | JDK | Default renderer | Available MarlinFX release |
12 | | --- | --- | --- |
13 | | Open JDK 9 | MarlinFX 0.7.5 | [MarlinFX 0.9.3.1 for JDK9+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.3.1) |
14 | | Open JDK 10 | MarlinFX 0.8.2 | [MarlinFX 0.9.3.1 for JDK9+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.3.1) |
15 | | Open JFX 11 | MarlinFX 0.9.2 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
16 | | Open JFX 12 | MarlinFX 0.9.3 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
17 | | Open JFX 13 | MarlinFX 0.9.3.1 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
18 | | Open JFX 14 | MarlinFX 0.9.3.1 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
19 | | Open JFX 15 | MarlinFX 0.9.3.1 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
20 | | Open JFX 16 | MarlinFX 0.9.3.1 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
21 | | Open JFX 17 | MarlinFX 0.9.3.1 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
22 | | Open JFX 18 | MarlinFX 0.9.3.1 | [MarlinFX 0.9.4.5 for JFX11+](https://github.com/bourgesl/marlin-fx/releases/tag/v0.9.4.5) |
23 |
24 |
25 | License
26 | =======
27 |
28 | As marlin is a fork from OpenJDK Pisces, its license is the OpenJDK's license = GPL2+CP:
29 |
30 | GNU General Public License, version 2,
31 | with the Classpath Exception
32 |
33 | The GNU General Public License (GPL)
34 |
35 | Version 2, June 1991
36 |
37 | See License.md
38 |
39 | Build
40 | =====
41 |
42 | Needs Maven + Oracle or Open JDK 1.8 (with JavaFX)
43 |
44 | The MarlinFX build produces a (big) JavaFX jar file patched with MarlinFX classes (com.sun.marlin + hacked ShapeUtil using the MarlinRasterizer) to be placed in the boot classpath as JavaFX 8 lies in the extension classpath (and can not be patched easily). Of course, such (complete) JavaFX jar depends on your JDK version and your platform (win, mac, linux ...) so the MarlinFX jar can not be distributed (license issue) nor shared across platforms (binary incompatiblity).
45 |
46 | Note: it does not modify the SW pipeline which still uses OpenPisces (for compatiblity issue).
47 |
48 | First time, import your local jfxrt.jar (from ``${java.home}/lib/ext/jfxrt.jar``) to your local maven repository or when you get the error 'Could not find artifact javafx:jfxrt:jar:local in central (https://repo.maven.apache.org/maven2)' :
49 |
50 | ``mvn process-resources``
51 |
52 | Then build MarlinFX:
53 |
54 | ``mvn clean install``
55 |
56 | or
57 |
58 | ``mvn -Dmaven.test.skip=true clean install`` (to skip running tests)
59 |
60 | The MarlinFX jar is available in the target folder like:
61 |
62 | ``target/marlinfx-0.x.y-Unsafe.jar``
63 |
64 |
65 | Usage
66 | =====
67 |
68 | For testing purposes (only), MarlinFX can be used with any JavaFX application running on Oracle or Open JDK 8 (and derived JVMs).
69 |
70 | Just put the marlinfx-x.y.jar file in the bootclasspath to let JavaFX use MarlinFX instead of OpenPisces (java rasterizer) and set the following system property prism.marlin=true/false (true by default):
71 |
72 | ``java -Xbootclasspath/p:[absolute or relative path]/marlinfx-0.7.5-Unsafe.jar -Dprism.marlin=true ...``
73 |
74 | For example to launch the JavaFX8 Ensemble demo:
75 |
76 | ``java -Xbootclasspath/p:/home/bourgesl/libs/marlin/branches/marlin-fx/target/marlinfx-0.7.5-Unsafe.jar -jar Ensemble8.jar``
77 |
78 | You should see MarlinFX in action and the following message will be present in the console:
79 | ```
80 | Marlin-FX[marlinFX-0.7.5-Unsafe-OpenJDK] (double) enabled.
81 | INFO: ===============================================================================
82 | INFO: Marlin software rasterizer = ENABLED
83 | INFO: Version = [marlinFX-0.7.5-Unsafe-OpenJDK]
84 | INFO: prism.marlin = com.sun.marlin.DRenderer
85 | INFO: prism.marlin.useThreadLocal = true
86 | INFO: prism.marlin.useRef = soft
87 | INFO: prism.marlin.edges = 4096
88 | INFO: prism.marlin.pixelsize = 2048
89 | INFO: prism.marlin.subPixel_log2_X = 3
90 | INFO: prism.marlin.subPixel_log2_Y = 3
91 | INFO: prism.marlin.blockSize_log2 = 5
92 | INFO: prism.marlin.forceRLE = false
93 | INFO: prism.marlin.forceNoRLE = false
94 | INFO: prism.marlin.useTileFlags = true
95 | INFO: prism.marlin.useTileFlags.useHeuristics = true
96 | INFO: prism.marlin.rleMinWidth = 64
97 | INFO: prism.marlin.useSimplifier = false
98 | INFO: prism.marlin.doStats = false
99 | INFO: prism.marlin.doMonitors = false
100 | INFO: prism.marlin.doChecks = true
101 | INFO: prism.marlin.log = true
102 | INFO: prism.marlin.useLogger = true
103 | INFO: prism.marlin.logCreateContext = false
104 | INFO: prism.marlin.logUnsafeMalloc = false
105 | INFO: Renderer settings:
106 | INFO: CUB_COUNT_LG = 2
107 | INFO: CUB_DEC_BND = 8.0
108 | INFO: CUB_INC_BND = 3.2
109 | INFO: QUAD_DEC_BND = 4.0
110 | INFO: INITIAL_EDGES_CAPACITY = 98304
111 | INFO: INITIAL_CROSSING_COUNT = 1024
112 | INFO: ===============================================================================
113 | ```
114 | Two pipelines are available based on Double (default) and Float numerical values. To select the MarlinFX pipeline, use the system property prism.marlin.double=true/false (true means Double, false means Float) and is indicated in the standard output.
115 |
116 |
117 | Enjoy and send us your feedback !
118 |
119 | Note: Marlin system properties have been renamed to use the prefix 'prism.marlin' like prism.marlin.log=true/false (true by default).
120 |
121 |
122 | Getting in touch
123 | ================
124 |
125 | Users and developers interested in the Marlin-renderer are kindly invited to join the [marlin-renderer](https://groups.google.com/forum/#!forum/marlin-renderer) Google Group.
126 |
127 |
128 | Related projects
129 | ===============
130 |
131 | [Marlin-renderer](https://github.com/bourgesl/marlin-renderer) is the main Marlin-renderer repository (java2D rendering engine).
132 | [Mapbench](https://github.com/bourgesl/mapbench) provides benchmarking tools based on real world map painted by the [GeoServer](http://geoserver.org/) WMS server
133 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 | org.marlin
9 | marlinfx
10 | jar
11 | 0.9.3.1-Unsafe
12 | Marlin software rasterizer
13 |
14 | https://github.com/bourgesl/marlin-renderer
15 |
16 |
17 | A pure Java renderer, derived from OpenJDK Pisces (GPL2+CP)
18 |
19 |
20 |
21 | yyyy/MM/dd HH:mm:ss
22 | false
23 |
24 | jfxrt.jar
25 | ${java.home}/lib/ext/${jfxrt.jar}
26 |
27 |
28 |
29 |
30 |
31 | src/main/resources
32 | true
33 |
34 |
35 |
36 |
37 | org.apache.maven.plugins
38 | maven-resources-plugin
39 | 2.6
40 |
41 | UTF-8
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-compiler-plugin
48 | 3.6.2
49 |
50 | 1.8
51 | 1.8
52 | true
53 | UTF-8
54 |
55 |
56 |
57 |
58 | maven-install-plugin
59 | 2.5.2
60 |
61 |
62 | validate
63 |
64 | install-file
65 |
66 |
67 | javafx
68 | jfxrt
69 | local
70 | jar
71 | ${jfxrt.path}
72 |
73 |
74 |
75 |
76 |
77 |
78 | org.apache.maven.plugins
79 | maven-shade-plugin
80 | 2.4.3
81 |
82 |
83 | package
84 |
85 | shade
86 |
87 |
88 | false
89 |
90 |
91 | javafx:jfxrt:jar:local
92 |
93 | com/sun/javafx/geom/Path2D*.class
94 | com/sun/javafx/sg/prism/NGCanvas*.class
95 | com/sun/prism/impl/BasicStroke*.class
96 | com/sun/prism/impl/ps/CachingShapeRep*.class
97 | com/sun/prism/impl/shape/ShapeUtil*.class
98 |
99 |
100 |
101 | org.marlin:marlinfx
102 |
103 | **/*
104 |
105 |
106 | test/**
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | org.apache.maven.plugins
117 | maven-surefire-plugin
118 | 2.20.1
119 |
120 | 1
121 | 1
122 |
123 | true
124 |
125 | -Dprism.marlin=true
126 | -DClipShapeTest.numTests=5000
127 | -Djava.util.logging.config.file=src/test/resources/logging.properties
128 | -Xbootclasspath/p:${basedir}/target/${project.build.finalName}.jar
129 |
130 |
131 |
132 | integration-tests
133 | integration-test
134 |
135 | test
136 |
137 |
138 |
139 | ${integration.skip}
140 |
141 |
142 | **/ClipShapeTest.java
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | javafx
153 | jfxrt
154 | local
155 |
156 |
157 |
158 | junit
159 | junit
160 | 4.12
161 | test
162 |
163 |
164 | org.hamcrest
165 | hamcrest-core
166 | 1.3
167 | test
168 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/rasterPerf.log:
--------------------------------------------------------------------------------
1 | --------------
2 | Native Pisces:
3 | --------------
4 | 1228697 10x10 Rectangle native non-AA rasterizations took 5290.89ms, 232228.79326540523 ops/sec
5 | 140716 100x100 Rectangle native non-AA rasterizations took 6448.01ms, 21823.167147693628 ops/sec
6 | 905292 10x10 Ellipse native non-AA rasterizations took 6311.08ms, 143444.8620521369 ops/sec
7 | 118440 100x100 Ellipse native non-AA rasterizations took 6759.62ms, 17521.695006524034 ops/sec
8 | 85947 100x100 Cubics native non-AA rasterizations took 7899.51ms, 10880.041926651147 ops/sec
9 | 148795 100x100 Quads native non-AA rasterizations took 6772.72ms, 21969.75513530753 ops/sec
10 |
11 | 574770 10x10 Rectangle native AA rasterizations took 2482.51ms, 231527.76826679448 ops/sec
12 | 57579 100x100 Rectangle native AA rasterizations took 2497.39ms, 23055.670119604867 ops/sec
13 | 360825 10x10 Ellipse native AA rasterizations took 2490.84ms, 144860.76986076985 ops/sec
14 | 43729 100x100 Ellipse native AA rasterizations took 2498.89ms, 17499.36972015575 ops/sec
15 | 27364 100x100 Cubics native AA rasterizations took 2497.62ms, 10956.030140693942 ops/sec
16 | 54946 100x100 Quads native AA rasterizations took 2499.65ms, 21981.477406836955 ops/sec
17 |
18 | --------------
19 | Open Pisces:
20 | --------------
21 | 1714159 10x10 Rectangle Java non-AA rasterizations took 8491.07ms, 201877.8552055277 ops/sec
22 | 111796 100x100 Rectangle Java non-AA rasterizations took 6669.15ms, 16763.155724492626 ops/sec
23 | 1043686 10x10 Ellipse Java non-AA rasterizations took 7728.42ms, 135045.19681901345 ops/sec
24 | 99690 100x100 Ellipse Java non-AA rasterizations took 7174.44ms, 13895.16115543513 ops/sec
25 | 74519 100x100 Cubics Java non-AA rasterizations took 7917.37ms, 9412.090125887764 ops/sec
26 | 128738 100x100 Quads Java non-AA rasterizations took 7561.9ms, 17024.557320250202 ops/sec
27 |
28 | 494692 10x10 Rectangle Java AA rasterizations took 2474.1ms, 199948.26401519746 ops/sec
29 | 41681 100x100 Rectangle Java AA rasterizations took 2503.33ms, 16650.22190442331 ops/sec
30 | 325037 10x10 Ellipse Java AA rasterizations took 2478.15ms, 131161.14843734237 ops/sec
31 | 34328 100x100 Ellipse Java AA rasterizations took 2501.93ms, 13720.607690862655 ops/sec
32 | 23519 100x100 Cubics Java AA rasterizations took 2499.45ms, 9409.670127428035 ops/sec
33 | 42646 100x100 Quads Java AA rasterizations took 2494.9ms, 17093.270271353562 ops/sec
34 |
35 | --------------
36 | Marlin:
37 | --------------
38 |
39 | 2096722 10x10 Rectangle Marlin non-AA rasterizations took 5948.66ms, 352469.63181624096 ops/sec
40 | 146539 100x100 Rectangle Marlin non-AA rasterizations took 4842.45ms, 30261.33465497837 ops/sec
41 | 32921 300x300 Rectangle Marlin non-AA rasterizations took 4427.83ms, 7435.0189596258215 ops/sec
42 | 1324006 10x10 Ellipse Marlin non-AA rasterizations took 5276.7ms, 250915.53433016848 ops/sec
43 | 88526 100x100 Ellipse Marlin non-AA rasterizations took 4015.3ms, 22047.169576370383 ops/sec
44 | 32493 300x300 Ellipse Marlin non-AA rasterizations took 4883.55ms, 6653.561446079184 ops/sec
45 | 84713 100x100 Cubics Marlin non-AA rasterizations took 5090.13ms, 16642.600483681163 ops/sec
46 | 166992 100x100 Quads Marlin non-AA rasterizations took 6500.0ms, 25691.076923076922 ops/sec
47 |
48 | 770788 10x10 Rectangle Marlin AA rasterizations took 2473.47ms, 311622.13408693054 ops/sec
49 | 72479 100x100 Rectangle Marlin AA rasterizations took 2495.7ms, 29041.551468525868 ops/sec
50 | 20650 300x300 Rectangle Marlin AA rasterizations took 2499.85ms, 8260.495629737785 ops/sec
51 | 636831 10x10 Ellipse Marlin AA rasterizations took 2476.56ms, 257143.37629615274 ops/sec
52 | 57208 100x100 Ellipse Marlin AA rasterizations took 2482.24ms, 23046.9253577414 ops/sec
53 | 16508 300x300 Ellipse Marlin AA rasterizations took 2497.73ms, 6609.201154648421 ops/sec
54 | 44000 100x100 Cubics Marlin AA rasterizations took 2496.32ms, 17625.945391616457 ops/sec
55 | 66399 100x100 Quads Marlin AA rasterizations took 2498.7ms, 26573.418177452277 ops/sec
56 |
57 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/javafx/sg/prism/NGCanvasPath.java:
--------------------------------------------------------------------------------
1 | package com.sun.javafx.sg.prism;
2 |
3 | import com.sun.javafx.geom.Path2D;
4 | import com.sun.javafx.geom.Shape;
5 | import com.sun.javafx.geom.transform.BaseTransform;
6 |
7 | /**
8 | * Type needed to be handled specifically by the Marlin renderer
9 | * @author bourgesl
10 | */
11 | public abstract class NGCanvasPath extends Shape {
12 |
13 | public abstract Path2D getGeometry();
14 |
15 | public abstract BaseTransform getCombinedTransform(BaseTransform tx);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/ArrayCacheConst.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | import java.util.Arrays;
29 | import static com.sun.marlin.MarlinUtils.logInfo;
30 |
31 | public final class ArrayCacheConst implements MarlinConst {
32 |
33 | static final int BUCKETS = 8;
34 | static final int MIN_ARRAY_SIZE = 4096;
35 | // maximum array size
36 | static final int MAX_ARRAY_SIZE;
37 | // threshold below to grow arrays by 4
38 | static final int THRESHOLD_SMALL_ARRAY_SIZE = 4 * 1024 * 1024;
39 | // threshold to grow arrays only by (3/2) instead of 2
40 | static final int THRESHOLD_ARRAY_SIZE;
41 | // threshold to grow arrays only by (5/4) instead of (3/2)
42 | static final long THRESHOLD_HUGE_ARRAY_SIZE;
43 | static final int[] ARRAY_SIZES = new int[BUCKETS];
44 |
45 | static {
46 | // initialize buckets for int/float arrays
47 | int arraySize = MIN_ARRAY_SIZE;
48 |
49 | int inc_lg = 2; // x4
50 |
51 | for (int i = 0; i < BUCKETS; i++, arraySize <<= inc_lg) {
52 | ARRAY_SIZES[i] = arraySize;
53 |
54 | if (DO_TRACE) {
55 | logInfo("arraySize[" + i + "]: " + arraySize);
56 | }
57 |
58 | if (arraySize >= THRESHOLD_SMALL_ARRAY_SIZE) {
59 | inc_lg = 1; // x2
60 | }
61 | }
62 | MAX_ARRAY_SIZE = arraySize >> inc_lg;
63 |
64 | if (MAX_ARRAY_SIZE <= 0) {
65 | throw new IllegalStateException("Invalid max array size !");
66 | }
67 |
68 | THRESHOLD_ARRAY_SIZE = 16 * 1024 * 1024; // >16M
69 | THRESHOLD_HUGE_ARRAY_SIZE = 48L * 1024 * 1024; // >48M
70 |
71 | if (DO_STATS || DO_MONITORS) {
72 | logInfo("ArrayCache.BUCKETS = " + BUCKETS);
73 | logInfo("ArrayCache.MIN_ARRAY_SIZE = " + MIN_ARRAY_SIZE);
74 | logInfo("ArrayCache.MAX_ARRAY_SIZE = " + MAX_ARRAY_SIZE);
75 | logInfo("ArrayCache.ARRAY_SIZES = "
76 | + Arrays.toString(ARRAY_SIZES));
77 | logInfo("ArrayCache.THRESHOLD_ARRAY_SIZE = "
78 | + THRESHOLD_ARRAY_SIZE);
79 | logInfo("ArrayCache.THRESHOLD_HUGE_ARRAY_SIZE = "
80 | + THRESHOLD_HUGE_ARRAY_SIZE);
81 | }
82 | }
83 |
84 | private ArrayCacheConst() {
85 | // Utility class
86 | }
87 |
88 | // small methods used a lot (to be inlined / optimized by hotspot)
89 |
90 | static int getBucket(final int length) {
91 | for (int i = 0; i < ARRAY_SIZES.length; i++) {
92 | if (length <= ARRAY_SIZES[i]) {
93 | return i;
94 | }
95 | }
96 | return -1;
97 | }
98 |
99 | /**
100 | * Return the new array size (~ x2)
101 | * @param curSize current used size
102 | * @param needSize needed size
103 | * @return new array size
104 | */
105 | public static int getNewSize(final int curSize, final int needSize) {
106 | // check if needSize is negative or integer overflow:
107 | if (needSize < 0) {
108 | // hard overflow failure - we can't even accommodate
109 | // new items without overflowing
110 | throw new ArrayIndexOutOfBoundsException(
111 | "array exceeds maximum capacity !");
112 | }
113 | assert curSize >= 0;
114 | final int initial = curSize;
115 | int size;
116 | if (initial > THRESHOLD_ARRAY_SIZE) {
117 | size = initial + (initial >> 1); // x(3/2)
118 | } else {
119 | size = (initial << 1); // x2
120 | }
121 | // ensure the new size is >= needed size:
122 | if (size < needSize) {
123 | // align to 4096 (may overflow):
124 | size = ((needSize >> 12) + 1) << 12;
125 | }
126 | // check integer overflow:
127 | if (size < 0) {
128 | // resize to maximum capacity:
129 | size = Integer.MAX_VALUE;
130 | }
131 | return size;
132 | }
133 |
134 | /**
135 | * Return the new array size (~ x2)
136 | * @param curSize current used size
137 | * @param needSize needed size
138 | * @return new array size
139 | */
140 | public static long getNewLargeSize(final long curSize, final long needSize) {
141 | // check if needSize is negative or integer overflow:
142 | if ((needSize >> 31L) != 0L) {
143 | // hard overflow failure - we can't even accommodate
144 | // new items without overflowing
145 | throw new ArrayIndexOutOfBoundsException(
146 | "array exceeds maximum capacity !");
147 | }
148 | assert curSize >= 0L;
149 | long size;
150 | if (curSize > THRESHOLD_HUGE_ARRAY_SIZE) {
151 | size = curSize + (curSize >> 2L); // x(5/4)
152 | } else if (curSize > THRESHOLD_ARRAY_SIZE) {
153 | size = curSize + (curSize >> 1L); // x(3/2)
154 | } else if (curSize > THRESHOLD_SMALL_ARRAY_SIZE) {
155 | size = (curSize << 1L); // x2
156 | } else {
157 | size = (curSize << 2L); // x4
158 | }
159 | // ensure the new size is >= needed size:
160 | if (size < needSize) {
161 | // align to 4096:
162 | size = ((needSize >> 12L) + 1L) << 12L;
163 | }
164 | // check integer overflow:
165 | if (size > Integer.MAX_VALUE) {
166 | // resize to maximum capacity:
167 | size = Integer.MAX_VALUE;
168 | }
169 | return size;
170 | }
171 |
172 | static final class CacheStats {
173 | final String name;
174 | final BucketStats[] bucketStats;
175 | int resize = 0;
176 | int oversize = 0;
177 | long totalInitial = 0L;
178 |
179 | CacheStats(final String name) {
180 | this.name = name;
181 |
182 | bucketStats = new BucketStats[BUCKETS];
183 | for (int i = 0; i < BUCKETS; i++) {
184 | bucketStats[i] = new BucketStats();
185 | }
186 | }
187 |
188 | void reset() {
189 | resize = 0;
190 | oversize = 0;
191 |
192 | for (int i = 0; i < BUCKETS; i++) {
193 | bucketStats[i].reset();
194 | }
195 | }
196 |
197 | long dumpStats() {
198 | long totalCacheBytes = 0L;
199 |
200 | if (DO_STATS) {
201 | for (int i = 0; i < BUCKETS; i++) {
202 | final BucketStats s = bucketStats[i];
203 |
204 | if (s.maxSize != 0) {
205 | totalCacheBytes += getByteFactor()
206 | * (s.maxSize * ARRAY_SIZES[i]);
207 | }
208 | }
209 |
210 | if (totalInitial != 0L || totalCacheBytes != 0L
211 | || resize != 0 || oversize != 0)
212 | {
213 | logInfo(name + ": resize: " + resize
214 | + " - oversize: " + oversize
215 | + " - initial: " + getTotalInitialBytes()
216 | + " bytes (" + totalInitial + " elements)"
217 | + " - cache: " + totalCacheBytes + " bytes"
218 | );
219 | }
220 |
221 | if (totalCacheBytes != 0L) {
222 | logInfo(name + ": usage stats:");
223 |
224 | for (int i = 0; i < BUCKETS; i++) {
225 | final BucketStats s = bucketStats[i];
226 |
227 | if (s.getOp != 0) {
228 | logInfo(" Bucket[" + ARRAY_SIZES[i] + "]: "
229 | + "get: " + s.getOp
230 | + " - put: " + s.returnOp
231 | + " - create: " + s.createOp
232 | + " :: max size: " + s.maxSize
233 | );
234 | }
235 | }
236 | }
237 | }
238 | return totalCacheBytes;
239 | }
240 |
241 | private int getByteFactor() {
242 | int factor = 1;
243 | if (name.contains("Int") || name.contains("Float")) {
244 | factor = 4;
245 | } else if (name.contains("Double")) {
246 | factor = 8;
247 | }
248 | return factor;
249 | }
250 |
251 | long getTotalInitialBytes() {
252 | return getByteFactor() * totalInitial;
253 | }
254 | }
255 |
256 | static final class BucketStats {
257 | int getOp = 0;
258 | int createOp = 0;
259 | int returnOp = 0;
260 | int maxSize = 0;
261 |
262 | void reset() {
263 | getOp = 0;
264 | createOp = 0;
265 | returnOp = 0;
266 | maxSize = 0;
267 | }
268 |
269 | void updateMaxSize(final int size) {
270 | if (size > maxSize) {
271 | maxSize = size;
272 | }
273 | }
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/CollinearSimplifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | import com.sun.javafx.geom.PathConsumer2D;
29 |
30 | public final class CollinearSimplifier implements PathConsumer2D {
31 |
32 | enum SimplifierState {
33 |
34 | Empty, PreviousPoint, PreviousLine
35 | };
36 | // slope precision threshold
37 | static final float EPS = 1e-4f; // aaime proposed 1e-3f
38 |
39 | PathConsumer2D delegate;
40 | SimplifierState state;
41 | float px1, py1, px2, py2;
42 | float pslope;
43 |
44 | CollinearSimplifier() {
45 | }
46 |
47 | public CollinearSimplifier init(PathConsumer2D delegate) {
48 | this.delegate = delegate;
49 | this.state = SimplifierState.Empty;
50 |
51 | return this; // fluent API
52 | }
53 |
54 | @Override
55 | public void pathDone() {
56 | emitStashedLine();
57 | state = SimplifierState.Empty;
58 | delegate.pathDone();
59 | }
60 |
61 | @Override
62 | public void closePath() {
63 | emitStashedLine();
64 | state = SimplifierState.Empty;
65 | delegate.closePath();
66 | }
67 |
68 | @Override
69 | public void quadTo(float x1, float y1, float x2, float y2) {
70 | emitStashedLine();
71 | delegate.quadTo(x1, y1, x2, y2);
72 | // final end point:
73 | state = SimplifierState.PreviousPoint;
74 | px1 = x2;
75 | py1 = y2;
76 | }
77 |
78 | @Override
79 | public void curveTo(float x1, float y1, float x2, float y2,
80 | float x3, float y3) {
81 | emitStashedLine();
82 | delegate.curveTo(x1, y1, x2, y2, x3, y3);
83 | // final end point:
84 | state = SimplifierState.PreviousPoint;
85 | px1 = x3;
86 | py1 = y3;
87 | }
88 |
89 | @Override
90 | public void moveTo(float x, float y) {
91 | emitStashedLine();
92 | delegate.moveTo(x, y);
93 | state = SimplifierState.PreviousPoint;
94 | px1 = x;
95 | py1 = y;
96 | }
97 |
98 | @Override
99 | public void lineTo(final float x, final float y) {
100 | switch (state) {
101 | case Empty:
102 | delegate.lineTo(x, y);
103 | state = SimplifierState.PreviousPoint;
104 | px1 = x;
105 | py1 = y;
106 | return;
107 |
108 | case PreviousPoint:
109 | state = SimplifierState.PreviousLine;
110 | px2 = x;
111 | py2 = y;
112 | pslope = getSlope(px1, py1, x, y);
113 | return;
114 |
115 | case PreviousLine:
116 | final float slope = getSlope(px2, py2, x, y);
117 | // test for collinearity
118 | if ((slope == pslope) || (Math.abs(pslope - slope) < EPS)) {
119 | // merge segments
120 | px2 = x;
121 | py2 = y;
122 | return;
123 | }
124 | // emit previous segment
125 | delegate.lineTo(px2, py2);
126 | px1 = px2;
127 | py1 = py2;
128 | px2 = x;
129 | py2 = y;
130 | pslope = slope;
131 | return;
132 | default:
133 | }
134 | }
135 |
136 | private void emitStashedLine() {
137 | if (state == SimplifierState.PreviousLine) {
138 | delegate.lineTo(px2, py2);
139 | }
140 | }
141 |
142 | private static float getSlope(float x1, float y1, float x2, float y2) {
143 | float dy = y2 - y1;
144 | if (dy == 0.0f) {
145 | return (x2 > x1) ? Float.POSITIVE_INFINITY
146 | : Float.NEGATIVE_INFINITY;
147 | }
148 | return (x2 - x1) / dy;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/DCollinearSimplifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 |
29 |
30 | public final class DCollinearSimplifier implements DPathConsumer2D {
31 |
32 | enum SimplifierState {
33 |
34 | Empty, PreviousPoint, PreviousLine
35 | };
36 | // slope precision threshold
37 | static final double EPS = 1e-4d; // aaime proposed 1e-3d
38 |
39 | DPathConsumer2D delegate;
40 | SimplifierState state;
41 | double px1, py1, px2, py2;
42 | double pslope;
43 |
44 | DCollinearSimplifier() {
45 | }
46 |
47 | public DCollinearSimplifier init(DPathConsumer2D delegate) {
48 | this.delegate = delegate;
49 | this.state = SimplifierState.Empty;
50 |
51 | return this; // fluent API
52 | }
53 |
54 | @Override
55 | public void pathDone() {
56 | emitStashedLine();
57 | state = SimplifierState.Empty;
58 | delegate.pathDone();
59 | }
60 |
61 | @Override
62 | public void closePath() {
63 | emitStashedLine();
64 | state = SimplifierState.Empty;
65 | delegate.closePath();
66 | }
67 |
68 | @Override
69 | public void quadTo(double x1, double y1, double x2, double y2) {
70 | emitStashedLine();
71 | delegate.quadTo(x1, y1, x2, y2);
72 | // final end point:
73 | state = SimplifierState.PreviousPoint;
74 | px1 = x2;
75 | py1 = y2;
76 | }
77 |
78 | @Override
79 | public void curveTo(double x1, double y1, double x2, double y2,
80 | double x3, double y3) {
81 | emitStashedLine();
82 | delegate.curveTo(x1, y1, x2, y2, x3, y3);
83 | // final end point:
84 | state = SimplifierState.PreviousPoint;
85 | px1 = x3;
86 | py1 = y3;
87 | }
88 |
89 | @Override
90 | public void moveTo(double x, double y) {
91 | emitStashedLine();
92 | delegate.moveTo(x, y);
93 | state = SimplifierState.PreviousPoint;
94 | px1 = x;
95 | py1 = y;
96 | }
97 |
98 | @Override
99 | public void lineTo(final double x, final double y) {
100 | switch (state) {
101 | case Empty:
102 | delegate.lineTo(x, y);
103 | state = SimplifierState.PreviousPoint;
104 | px1 = x;
105 | py1 = y;
106 | return;
107 |
108 | case PreviousPoint:
109 | state = SimplifierState.PreviousLine;
110 | px2 = x;
111 | py2 = y;
112 | pslope = getSlope(px1, py1, x, y);
113 | return;
114 |
115 | case PreviousLine:
116 | final double slope = getSlope(px2, py2, x, y);
117 | // test for collinearity
118 | if ((slope == pslope) || (Math.abs(pslope - slope) < EPS)) {
119 | // merge segments
120 | px2 = x;
121 | py2 = y;
122 | return;
123 | }
124 | // emit previous segment
125 | delegate.lineTo(px2, py2);
126 | px1 = px2;
127 | py1 = py2;
128 | px2 = x;
129 | py2 = y;
130 | pslope = slope;
131 | return;
132 | default:
133 | }
134 | }
135 |
136 | private void emitStashedLine() {
137 | if (state == SimplifierState.PreviousLine) {
138 | delegate.lineTo(px2, py2);
139 | }
140 | }
141 |
142 | private static double getSlope(double x1, double y1, double x2, double y2) {
143 | double dy = y2 - y1;
144 | if (dy == 0.0d) {
145 | return (x2 > x1) ? Double.POSITIVE_INFINITY
146 | : Double.NEGATIVE_INFINITY;
147 | }
148 | return (x2 - x1) / dy;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/DMarlinRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | public interface DMarlinRenderer extends DPathConsumer2D {
29 |
30 | public DMarlinRenderer init(final int pix_boundsX, final int pix_boundsY,
31 | final int pix_boundsWidth, final int pix_boundsHeight,
32 | final int windingRule);
33 |
34 | /**
35 | * Disposes this renderer and recycle it clean up before reusing this instance
36 | */
37 | public void dispose();
38 |
39 | public int getOutpixMinX();
40 | public int getOutpixMaxX();
41 | public int getOutpixMinY();
42 | public int getOutpixMaxY();
43 |
44 | public void produceAlphas(MarlinAlphaConsumer ac);
45 |
46 | public double getOffsetX();
47 | public double getOffsetY();
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/DPathConsumer2D.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | public interface DPathConsumer2D {
29 | public void moveTo(double x0, double y0);
30 | public void lineTo(double x1, double y1);
31 | public void quadTo(double xc, double yc,
32 | double x1, double y1);
33 | public void curveTo(double xc0, double yc0,
34 | double xc1, double yc1,
35 | double x1, double y1);
36 | public void closePath();
37 | public void pathDone();
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/DPathSimplifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | public final class DPathSimplifier implements DPathConsumer2D {
29 |
30 | // distance threshold in pixels (device)
31 | private static final double PIX_THRESHOLD = MarlinProperties.getPathSimplifierPixelTolerance();
32 | // squared tolerance in pixels
33 | private static final double SQUARE_TOLERANCE = PIX_THRESHOLD * PIX_THRESHOLD;
34 |
35 | // members:
36 | private DPathConsumer2D delegate;
37 | // current reference point
38 | private double cx, cy;
39 | // flag indicating if the given point was skipped
40 | private boolean skipped;
41 | // last skipped point
42 | private double sx, sy;
43 |
44 | DPathSimplifier() {
45 | }
46 |
47 | public DPathSimplifier init(final DPathConsumer2D delegate) {
48 | this.delegate = delegate;
49 | skipped = false;
50 | return this; // fluent API
51 | }
52 |
53 | private void finishPath() {
54 | if (skipped) {
55 | _lineTo(sx, sy);
56 | }
57 | }
58 |
59 | @Override
60 | public void pathDone() {
61 | finishPath();
62 | delegate.pathDone();
63 | }
64 |
65 | @Override
66 | public void closePath() {
67 | finishPath();
68 | delegate.closePath();
69 | }
70 |
71 | @Override
72 | public void moveTo(final double xe, final double ye) {
73 | finishPath();
74 | delegate.moveTo(xe, ye);
75 | cx = xe;
76 | cy = ye;
77 | }
78 |
79 | @Override
80 | public void lineTo(final double xe, final double ye) {
81 | // Test if segment is too small:
82 | double dx = (xe - cx);
83 | double dy = (ye - cy);
84 |
85 | if ((dx * dx + dy * dy) <= SQUARE_TOLERANCE) {
86 | skipped = true;
87 | sx = xe;
88 | sy = ye;
89 | return;
90 | }
91 | _lineTo(xe, ye);
92 | }
93 |
94 | private void _lineTo(final double xe, final double ye) {
95 | delegate.lineTo(xe, ye);
96 | cx = xe;
97 | cy = ye;
98 | skipped = false;
99 | }
100 |
101 | @Override
102 | public void quadTo(final double x1, final double y1,
103 | final double xe, final double ye)
104 | {
105 | // Test if curve is too small:
106 | double dx = (xe - cx);
107 | double dy = (ye - cy);
108 |
109 | if ((dx * dx + dy * dy) <= SQUARE_TOLERANCE) {
110 | // check control points P1:
111 | dx = (x1 - cx);
112 | dy = (y1 - cy);
113 |
114 | if ((dx * dx + dy * dy) <= SQUARE_TOLERANCE) {
115 | skipped = true;
116 | sx = xe;
117 | sy = ye;
118 | return;
119 | }
120 | }
121 | delegate.quadTo(x1, y1, xe, ye);
122 | cx = xe;
123 | cy = ye;
124 | skipped = false;
125 | }
126 |
127 | @Override
128 | public void curveTo(final double x1, final double y1,
129 | final double x2, final double y2,
130 | final double xe, final double ye)
131 | {
132 | // Test if curve is too small:
133 | double dx = (xe - cx);
134 | double dy = (ye - cy);
135 |
136 | if ((dx * dx + dy * dy) <= SQUARE_TOLERANCE) {
137 | // check control points P1:
138 | dx = (x1 - cx);
139 | dy = (y1 - cy);
140 |
141 | if ((dx * dx + dy * dy) <= SQUARE_TOLERANCE) {
142 | // check control points P2:
143 | dx = (x2 - cx);
144 | dy = (y2 - cy);
145 |
146 | if ((dx * dx + dy * dy) <= SQUARE_TOLERANCE) {
147 | skipped = true;
148 | sx = xe;
149 | sy = ye;
150 | return;
151 | }
152 | }
153 | }
154 | delegate.curveTo(x1, y1, x2, y2, xe, ye);
155 | cx = xe;
156 | cy = ye;
157 | skipped = false;
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/FloatMath.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | /**
29 | * Faster Math ceil / floor routines derived from StrictMath
30 | */
31 | public final class FloatMath implements MarlinConst {
32 |
33 | // overflow / NaN handling enabled:
34 | static final boolean CHECK_OVERFLOW = true;
35 | static final boolean CHECK_NAN = true;
36 |
37 | private FloatMath() {
38 | // utility class
39 | }
40 |
41 | // faster inlined min/max functions in the branch prediction is high
42 | public static int max(final int a, final int b) {
43 | return (a >= b) ? a : b;
44 | }
45 |
46 | public static int min(final int a, final int b) {
47 | return (a <= b) ? a : b;
48 | }
49 |
50 | /**
51 | * Faster alternative to ceil(float) optimized for the integer domain
52 | * and supporting NaN and +/-Infinity.
53 | *
54 | * @param a a value.
55 | * @return the largest (closest to positive infinity) integer value
56 | * that less than or equal to the argument and is equal to a mathematical
57 | * integer.
58 | */
59 | public static int ceil_int(final float a) {
60 | final int intpart = (int) a;
61 |
62 | if (a <= intpart
63 | || (CHECK_OVERFLOW && intpart == Integer.MAX_VALUE)
64 | || CHECK_NAN && Float.isNaN(a)) {
65 | return intpart;
66 | }
67 | return intpart + 1;
68 | }
69 |
70 | /**
71 | * Faster alternative to ceil(double) optimized for the integer domain
72 | * and supporting NaN and +/-Infinity.
73 | *
74 | * @param a a value.
75 | * @return the largest (closest to positive infinity) integer value
76 | * that less than or equal to the argument and is equal to a mathematical
77 | * integer.
78 | */
79 | public static int ceil_int(final double a) {
80 | final int intpart = (int) a;
81 |
82 | if (a <= intpart
83 | || (CHECK_OVERFLOW && intpart == Integer.MAX_VALUE)
84 | || CHECK_NAN && Double.isNaN(a)) {
85 | return intpart;
86 | }
87 | return intpart + 1;
88 | }
89 |
90 | /**
91 | * Faster alternative to floor(float) optimized for the integer domain
92 | * and supporting NaN and +/-Infinity.
93 | *
94 | * @param a a value.
95 | * @return the largest (closest to positive infinity) floating-point value
96 | * that less than or equal to the argument and is equal to a mathematical
97 | * integer.
98 | */
99 | public static int floor_int(final float a) {
100 | final int intpart = (int) a;
101 |
102 | if (a >= intpart
103 | || (CHECK_OVERFLOW && intpart == Integer.MIN_VALUE)
104 | || CHECK_NAN && Float.isNaN(a)) {
105 | return intpart;
106 | }
107 | return intpart - 1;
108 | }
109 |
110 | /**
111 | * Faster alternative to floor(double) optimized for the integer domain
112 | * and supporting NaN and +/-Infinity.
113 | *
114 | * @param a a value.
115 | * @return the largest (closest to positive infinity) floating-point value
116 | * that less than or equal to the argument and is equal to a mathematical
117 | * integer.
118 | */
119 | public static int floor_int(final double a) {
120 | final int intpart = (int) a;
121 |
122 | if (a >= intpart
123 | || (CHECK_OVERFLOW && intpart == Integer.MIN_VALUE)
124 | || CHECK_NAN && Double.isNaN(a)) {
125 | return intpart;
126 | }
127 | return intpart - 1;
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/MarlinAlphaConsumer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | import com.sun.openpisces.AlphaConsumer;
29 |
30 | public interface MarlinAlphaConsumer extends AlphaConsumer {
31 |
32 | public boolean supportBlockFlags();
33 |
34 | public void clearAlphas(final int pix_y);
35 |
36 | public void setAndClearRelativeAlphas(int[] blkFlags, int alphaDeltas[], int pix_y,
37 | int firstdelta, int lastdelta);
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/MarlinConst.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | /**
29 | * Marlin constant holder using System properties
30 | */
31 | public interface MarlinConst {
32 | // enable Logs (logger or stdout)
33 | static final boolean ENABLE_LOGS = MarlinProperties.isLoggingEnabled();
34 | // use Logger instead of stdout
35 | static final boolean USE_LOGGER = ENABLE_LOGS && MarlinProperties.isUseLogger();
36 |
37 | // log new RendererContext
38 | static final boolean LOG_CREATE_CONTEXT = ENABLE_LOGS
39 | && MarlinProperties.isLogCreateContext();
40 | // log misc.Unsafe alloc/realloc/free
41 | static final boolean LOG_UNSAFE_MALLOC = ENABLE_LOGS
42 | && MarlinProperties.isLogUnsafeMalloc();
43 | // do check unsafe alignment:
44 | static final boolean DO_CHECK_UNSAFE = false;
45 |
46 | // do statistics
47 | static final boolean DO_STATS = ENABLE_LOGS && MarlinProperties.isDoStats();
48 | // do monitors
49 | // disabled to reduce byte-code size a bit...
50 | static final boolean DO_MONITORS = false;
51 | // static final boolean DO_MONITORS = ENABLE_LOGS && MarlinProperties.isDoMonitors();
52 | // do checks
53 | static final boolean DO_CHECKS = ENABLE_LOGS && MarlinProperties.isDoChecks();
54 |
55 | // do AA range checks: disable when algorithm / code is stable
56 | static final boolean DO_AA_RANGE_CHECK = false;
57 |
58 | // enable logs
59 | static final boolean DO_LOG_WIDEN_ARRAY = ENABLE_LOGS && false;
60 | // enable oversize logs
61 | static final boolean DO_LOG_OVERSIZE = ENABLE_LOGS && false;
62 | // enable traces
63 | static final boolean DO_TRACE = ENABLE_LOGS && false;
64 |
65 | // do flush stats
66 | static final boolean DO_FLUSH_STATS = true;
67 | // do flush monitors
68 | static final boolean DO_FLUSH_MONITORS = true;
69 | // use one polling thread to dump statistics/monitors
70 | static final boolean USE_DUMP_THREAD = false;
71 | // thread dump interval (ms)
72 | static final long DUMP_INTERVAL = 5000L;
73 |
74 | // do clean dirty array
75 | static final boolean DO_CLEAN_DIRTY = false;
76 |
77 | // flag to use collinear simplifier
78 | static final boolean USE_SIMPLIFIER = MarlinProperties.isUseSimplifier();
79 |
80 | // flag to use path simplifier
81 | static final boolean USE_PATH_SIMPLIFIER = MarlinProperties.isUsePathSimplifier();
82 |
83 | static final boolean DO_CLIP_SUBDIVIDER = MarlinProperties.isDoClipSubdivider();
84 |
85 | // flag to enable logs related to bounds checks
86 | static final boolean DO_LOG_BOUNDS = ENABLE_LOGS && false;
87 |
88 | // flag to enable logs related to clip rect
89 | static final boolean DO_LOG_CLIP = ENABLE_LOGS && false;
90 |
91 | // Initial Array sizing (initial context capacity) ~ 450K
92 |
93 | // 4096 pixels (width) for initial capacity
94 | static final int INITIAL_PIXEL_WIDTH
95 | = MarlinProperties.getInitialPixelWidth();
96 | // 2176 pixels (height) for initial capacity
97 | static final int INITIAL_PIXEL_HEIGHT
98 | = MarlinProperties.getInitialPixelHeight();
99 |
100 | // typical array sizes: only odd numbers allowed below
101 | static final int INITIAL_ARRAY = 256;
102 |
103 | // alpha row dimension
104 | static final int INITIAL_AA_ARRAY = INITIAL_PIXEL_WIDTH;
105 |
106 | // 4096 edges for initial capacity
107 | static final int INITIAL_EDGES_COUNT = MarlinProperties.getInitialEdges();
108 |
109 | // initial edges = edges count (4096)
110 | // 6 ints per edges = 24 bytes
111 | // edges capacity = 24 x initial edges = 24 * edges count (4096) = 96K
112 | static final int INITIAL_EDGES_CAPACITY = INITIAL_EDGES_COUNT * 24;
113 |
114 | // crossing capacity = edges count / 4 ~ 1024
115 | static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
116 |
117 | // zero value as byte
118 | static final byte BYTE_0 = (byte) 0;
119 |
120 | // subpixels expressed as log2
121 | public static final int SUBPIXEL_LG_POSITIONS_X
122 | = MarlinProperties.getSubPixel_Log2_X();
123 | public static final int SUBPIXEL_LG_POSITIONS_Y
124 | = MarlinProperties.getSubPixel_Log2_Y();
125 |
126 | public static final int MIN_SUBPIXEL_LG_POSITIONS
127 | = Math.min(SUBPIXEL_LG_POSITIONS_X, SUBPIXEL_LG_POSITIONS_Y);
128 |
129 | // number of subpixels
130 | public static final int SUBPIXEL_POSITIONS_X = 1 << (SUBPIXEL_LG_POSITIONS_X);
131 | public static final int SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
132 |
133 | public static final float MIN_SUBPIXELS = 1 << MIN_SUBPIXEL_LG_POSITIONS;
134 |
135 | // 2176 pixels (height) x 8 subpixels = 68K
136 | static final int INITIAL_BUCKET_ARRAY
137 | = INITIAL_PIXEL_HEIGHT * SUBPIXEL_POSITIONS_Y;
138 |
139 | public static final int MAX_AA_ALPHA
140 | = (SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y);
141 |
142 | public static final int BLOCK_SIZE_LG = MarlinProperties.getBlockSize_Log2();
143 | public static final int BLOCK_SIZE = 1 << BLOCK_SIZE_LG;
144 |
145 | static final boolean ENABLE_BLOCK_FLAGS = MarlinProperties.isUseTileFlags();
146 | static final boolean ENABLE_BLOCK_FLAGS_HEURISTICS = MarlinProperties.isUseTileFlagsWithHeuristics();
147 |
148 | static final boolean FORCE_RLE = MarlinProperties.isForceRLE();
149 | static final boolean FORCE_NO_RLE = MarlinProperties.isForceNoRLE();
150 | // minimum width to try using RLE encoding:
151 | static final int RLE_MIN_WIDTH
152 | = Math.max(BLOCK_SIZE, MarlinProperties.getRLEMinWidth());
153 |
154 | // Constants
155 | public static final int WIND_EVEN_ODD = 0;
156 | public static final int WIND_NON_ZERO = 1;
157 |
158 | /**
159 | * Constant value for join style.
160 | */
161 | public static final int JOIN_MITER = 0;
162 |
163 | /**
164 | * Constant value for join style.
165 | */
166 | public static final int JOIN_ROUND = 1;
167 |
168 | /**
169 | * Constant value for join style.
170 | */
171 | public static final int JOIN_BEVEL = 2;
172 |
173 | /**
174 | * Constant value for end cap style.
175 | */
176 | public static final int CAP_BUTT = 0;
177 |
178 | /**
179 | * Constant value for end cap style.
180 | */
181 | public static final int CAP_ROUND = 1;
182 |
183 | /**
184 | * Constant value for end cap style.
185 | */
186 | public static final int CAP_SQUARE = 2;
187 |
188 | // Out codes
189 | static final int OUTCODE_TOP = 1;
190 | static final int OUTCODE_BOTTOM = 2;
191 | static final int OUTCODE_LEFT = 4;
192 | static final int OUTCODE_RIGHT = 8;
193 | static final int OUTCODE_MASK_T_B = OUTCODE_TOP | OUTCODE_BOTTOM;
194 | static final int OUTCODE_MASK_L_R = OUTCODE_LEFT | OUTCODE_RIGHT;
195 | static final int OUTCODE_MASK_T_B_L_R = OUTCODE_MASK_T_B | OUTCODE_MASK_L_R;
196 | }
197 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/MarlinRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | import com.sun.javafx.geom.PathConsumer2D;
29 |
30 | public interface MarlinRenderer extends PathConsumer2D {
31 |
32 | public MarlinRenderer init(final int pix_boundsX, final int pix_boundsY,
33 | final int pix_boundsWidth, final int pix_boundsHeight,
34 | final int windingRule);
35 |
36 | /**
37 | * Disposes this renderer and recycle it clean up before reusing this instance
38 | */
39 | public void dispose();
40 |
41 | public int getOutpixMinX();
42 | public int getOutpixMaxX();
43 | public int getOutpixMinY();
44 | public int getOutpixMaxY();
45 |
46 | public void produceAlphas(MarlinAlphaConsumer ac);
47 |
48 | public float getOffsetX();
49 | public float getOffsetY();
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/MarlinUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | public final class MarlinUtils {
29 | // Marlin logger
30 | private static final java.util.logging.Logger LOG;
31 |
32 | static {
33 | if (MarlinConst.USE_LOGGER) {
34 | LOG = java.util.logging.Logger.getLogger("prism.marlin");
35 | } else {
36 | LOG = null;
37 | }
38 | }
39 |
40 | private MarlinUtils() {
41 | // no-op
42 | }
43 |
44 | public static void logInfo(final String msg) {
45 | if (MarlinConst.USE_LOGGER) {
46 | LOG.info(msg);
47 | } else if (MarlinConst.ENABLE_LOGS) {
48 | System.out.print("INFO: ");
49 | System.out.println(msg);
50 | }
51 | }
52 |
53 | public static void logException(final String msg, final Throwable th) {
54 | if (MarlinConst.USE_LOGGER) {
55 | LOG.log(java.util.logging.Level.WARNING, msg, th);
56 | } else if (MarlinConst.ENABLE_LOGS) {
57 | System.out.print("WARNING: ");
58 | System.out.println(msg);
59 | th.printStackTrace(System.err);
60 | }
61 | }
62 |
63 | // From sun.awt.util.ThreadGroupUtils
64 |
65 | /**
66 | * Returns a root thread group.
67 | * Should be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION}
68 | *
69 | * @return a root {@code ThreadGroup}
70 | */
71 | public static ThreadGroup getRootThreadGroup() {
72 | ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
73 | ThreadGroup parentTG = currentTG.getParent();
74 | while (parentTG != null) {
75 | currentTG = parentTG;
76 | parentTG = currentTG.getParent();
77 | }
78 | return currentTG;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/MergeSort.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | /**
29 | * MergeSort adapted from (OpenJDK 8) java.util.Array.legacyMergeSort(Object[])
30 | * to swap two arrays at the same time (x & y)
31 | * and use external auxiliary storage for temporary arrays
32 | */
33 | final class MergeSort {
34 |
35 | // insertion sort threshold
36 | public static final int INSERTION_SORT_THRESHOLD = 14;
37 |
38 | /**
39 | * Modified merge sort:
40 | * Input arrays are in both auxX/auxY (sorted: 0 to insertionSortIndex)
41 | * and x/y (unsorted: insertionSortIndex to toIndex)
42 | * Outputs are stored in x/y arrays
43 | */
44 | static void mergeSortNoCopy(final int[] x, final int[] y,
45 | final int[] auxX, final int[] auxY,
46 | final int toIndex,
47 | final int insertionSortIndex)
48 | {
49 | if ((toIndex > x.length) || (toIndex > y.length)
50 | || (toIndex > auxX.length) || (toIndex > auxY.length)) {
51 | // explicit check to avoid bound checks within hot loops (below):
52 | throw new ArrayIndexOutOfBoundsException("bad arguments: toIndex="
53 | + toIndex);
54 | }
55 |
56 | // sort second part only using merge / insertion sort
57 | // in auxiliary storage (auxX/auxY)
58 | mergeSort(x, y, x, auxX, y, auxY, insertionSortIndex, toIndex);
59 |
60 | // final pass to merge both
61 | // Merge sorted parts (auxX/auxY) into x/y arrays
62 | if ((insertionSortIndex == 0)
63 | || (auxX[insertionSortIndex - 1] <= auxX[insertionSortIndex])) {
64 | // 34 occurences
65 | // no initial left part or both sublists (auxX, auxY) are sorted:
66 | // copy back data into (x, y):
67 | System.arraycopy(auxX, 0, x, 0, toIndex);
68 | System.arraycopy(auxY, 0, y, 0, toIndex);
69 | return;
70 | }
71 |
72 | for (int i = 0, p = 0, q = insertionSortIndex; i < toIndex; i++) {
73 | if ((q >= toIndex) || ((p < insertionSortIndex)
74 | && (auxX[p] <= auxX[q]))) {
75 | x[i] = auxX[p];
76 | y[i] = auxY[p];
77 | p++;
78 | } else {
79 | x[i] = auxX[q];
80 | y[i] = auxY[q];
81 | q++;
82 | }
83 | }
84 | }
85 |
86 | /**
87 | * Src is the source array that starts at index 0
88 | * Dest is the (possibly larger) array destination with a possible offset
89 | * low is the index in dest to start sorting
90 | * high is the end index in dest to end sorting
91 | */
92 | private static void mergeSort(final int[] refX, final int[] refY,
93 | final int[] srcX, final int[] dstX,
94 | final int[] srcY, final int[] dstY,
95 | final int low, final int high)
96 | {
97 | final int length = high - low;
98 |
99 | /*
100 | * Tuning parameter: list size at or below which insertion sort
101 | * will be used in preference to mergesort.
102 | */
103 | if (length <= INSERTION_SORT_THRESHOLD) {
104 | // Insertion sort on smallest arrays
105 | dstX[low] = refX[low];
106 | dstY[low] = refY[low];
107 |
108 | for (int i = low + 1, j = low, x, y; i < high; j = i++) {
109 | x = refX[i];
110 | y = refY[i];
111 |
112 | while (dstX[j] > x) {
113 | // swap element
114 | dstX[j + 1] = dstX[j];
115 | dstY[j + 1] = dstY[j];
116 | if (j-- == low) {
117 | break;
118 | }
119 | }
120 | dstX[j + 1] = x;
121 | dstY[j + 1] = y;
122 | }
123 | return;
124 | }
125 |
126 | // Recursively sort halves of dest into src
127 |
128 | // note: use signed shift (not >>>) for performance
129 | // as indices are small enough to exceed Integer.MAX_VALUE
130 | final int mid = (low + high) >> 1;
131 |
132 | mergeSort(refX, refY, dstX, srcX, dstY, srcY, low, mid);
133 | mergeSort(refX, refY, dstX, srcX, dstY, srcY, mid, high);
134 |
135 | // If arrays are inverted ie all(A) > all(B) do swap A and B to dst
136 | if (srcX[high - 1] <= srcX[low]) {
137 | // 1561 occurences
138 | final int left = mid - low;
139 | final int right = high - mid;
140 | final int off = (left != right) ? 1 : 0;
141 | // swap parts:
142 | System.arraycopy(srcX, low, dstX, mid + off, left);
143 | System.arraycopy(srcX, mid, dstX, low, right);
144 | System.arraycopy(srcY, low, dstY, mid + off, left);
145 | System.arraycopy(srcY, mid, dstY, low, right);
146 | return;
147 | }
148 |
149 | // If arrays are already sorted, just copy from src to dest. This is an
150 | // optimization that results in faster sorts for nearly ordered lists.
151 | if (srcX[mid - 1] <= srcX[mid]) {
152 | // 14 occurences
153 | System.arraycopy(srcX, low, dstX, low, length);
154 | System.arraycopy(srcY, low, dstY, low, length);
155 | return;
156 | }
157 |
158 | // Merge sorted halves (now in src) into dest
159 | for (int i = low, p = low, q = mid; i < high; i++) {
160 | if ((q >= high) || ((p < mid) && (srcX[p] <= srcX[q]))) {
161 | dstX[i] = srcX[p];
162 | dstY[i] = srcY[p];
163 | p++;
164 | } else {
165 | dstX[i] = srcX[q];
166 | dstY[i] = srcY[q];
167 | q++;
168 | }
169 | }
170 | }
171 |
172 | private MergeSort() {
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/main/java/com/sun/marlin/OffHeapArray.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | package com.sun.marlin;
27 |
28 | import java.lang.ref.PhantomReference;
29 | import java.lang.ref.ReferenceQueue;
30 | import java.lang.reflect.Field;
31 | import java.security.AccessController;
32 | import java.security.PrivilegedAction;
33 | import java.util.Vector;
34 | import static com.sun.marlin.MarlinConst.LOG_UNSAFE_MALLOC;
35 | import sun.misc.Unsafe;
36 |
37 | /**
38 | *
39 | */
40 | final class OffHeapArray {
41 |
42 | // unsafe reference
43 | static final Unsafe UNSAFE;
44 | // size of int / float
45 | static final int SIZE_INT;
46 |
47 | static {
48 | UNSAFE = AccessController.doPrivileged(new PrivilegedAction() {
49 | @Override
50 | public Unsafe run() {
51 | Unsafe ref = null;
52 | try {
53 | final Field field = Unsafe.class.getDeclaredField("theUnsafe");
54 | field.setAccessible(true);
55 | ref = (Unsafe) field.get(null);
56 | } catch (Exception e) {
57 | throw new InternalError("Unable to get sun.misc.Unsafe instance", e);
58 | }
59 | return ref;
60 | }
61 | });
62 |
63 | SIZE_INT = Unsafe.ARRAY_INT_INDEX_SCALE;
64 |
65 | // Mimics Java2D Disposer:
66 | AccessController.doPrivileged(
67 | (PrivilegedAction) () -> {
68 | /*
69 | * The thread must be a member of a thread group
70 | * which will not get GCed before VM exit.
71 | * Make its parent the top-level thread group.
72 | */
73 | final Thread t = new Thread(
74 | MarlinUtils.getRootThreadGroup(),
75 | new OffHeapDisposer(),
76 | "MarlinRenderer Disposer");
77 | t.setContextClassLoader(null);
78 | t.setDaemon(true);
79 | t.setPriority(Thread.MAX_PRIORITY - 2);
80 | t.start();
81 | return null;
82 | }
83 | );
84 | }
85 |
86 | /* members */
87 | long address;
88 | long length;
89 | int used;
90 |
91 | OffHeapArray(final Object parent, final long len) {
92 | // note: may throw OOME:
93 | this.address = UNSAFE.allocateMemory(len);
94 | this.length = len;
95 | this.used = 0;
96 | if (LOG_UNSAFE_MALLOC) {
97 | MarlinUtils.logInfo(System.currentTimeMillis()
98 | + ": OffHeapArray.allocateMemory = "
99 | + len + " to addr = " + this.address);
100 | }
101 |
102 | // Create the phantom reference to ensure freeing off-heap memory:
103 | REF_LIST.add(new OffHeapReference(parent, this));
104 | }
105 |
106 | /*
107 | * As realloc may change the address, updating address is MANDATORY
108 | * @param len new array length
109 | * @throws OutOfMemoryError if the allocation is refused by the system
110 | */
111 | void resize(final long len) {
112 | // note: may throw OOME:
113 | this.address = UNSAFE.reallocateMemory(address, len);
114 | this.length = len;
115 | if (LOG_UNSAFE_MALLOC) {
116 | MarlinUtils.logInfo(System.currentTimeMillis()
117 | + ": OffHeapArray.reallocateMemory = "
118 | + len + " to addr = " + this.address);
119 | }
120 | }
121 |
122 | void free() {
123 | UNSAFE.freeMemory(this.address);
124 | if (LOG_UNSAFE_MALLOC) {
125 | MarlinUtils.logInfo(System.currentTimeMillis()
126 | + ": OffHeapArray.freeMemory = "
127 | + this.length
128 | + " at addr = " + this.address);
129 | }
130 | this.address = 0L;
131 | }
132 |
133 | void fill(final byte val) {
134 | UNSAFE.setMemory(this.address, this.length, val);
135 | }
136 |
137 | // Custom disposer (replaced by jdk9 Cleaner)
138 |
139 | // Parent reference queue
140 | private static final ReferenceQueue