1/*
2 * Copyright (c) 2007, 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
26package sun.java2d.marlin;
27
28import java.security.AccessController;
29import static sun.java2d.marlin.MarlinUtils.logInfo;
30import sun.security.action.GetPropertyAction;
31
32public final class MarlinProperties {
33
34    private MarlinProperties() {
35        // no-op
36    }
37
38    // marlin system properties
39
40    public static boolean isUseThreadLocal() {
41        return getBoolean("sun.java2d.renderer.useThreadLocal", "true");
42    }
43
44    /**
45     * Return the initial edge capacity used to define initial arrays
46     * (edges, polystack, crossings)
47     *
48     * @return 256 < initial edges < 65536 (4096 by default)
49     */
50    public static int getInitialEdges() {
51        return align(
52            getInteger("sun.java2d.renderer.edges", 4096, 64, 64 * 1024),
53            64);
54    }
55
56    /**
57     * Return the initial pixel size used to define initial arrays
58     * (tile AA chunk, alpha line, buckets)
59     *
60     * @return 64 < initial pixel size < 32768 (2048 by default)
61     */
62    public static int getInitialImageSize() {
63        return align(
64            getInteger("sun.java2d.renderer.pixelsize", 2048, 64, 32 * 1024),
65            64);
66    }
67
68    /**
69     * Return the log(2) corresponding to subpixel on x-axis (
70     *
71     * @return 0 (1 subpixels) < initial pixel size < 8 (256 subpixels)
72     * (3 by default ie 8 subpixels)
73     */
74    public static int getSubPixel_Log2_X() {
75        return getInteger("sun.java2d.renderer.subPixel_log2_X", 3, 0, 8);
76    }
77
78    /**
79     * Return the log(2) corresponding to subpixel on y-axis (
80     *
81     * @return 0 (1 subpixels) < initial pixel size < 8 (256 subpixels)
82     * (3 by default ie 8 subpixels)
83     */
84    public static int getSubPixel_Log2_Y() {
85        return getInteger("sun.java2d.renderer.subPixel_log2_Y", 3, 0, 8);
86    }
87
88    /**
89     * Return the log(2) corresponding to the square tile size in pixels
90     *
91     * @return 3 (8x8 pixels) < tile size < 8 (256x256 pixels)
92     * (5 by default ie 32x32 pixels)
93     */
94    public static int getTileSize_Log2() {
95        return getInteger("sun.java2d.renderer.tileSize_log2", 5, 3, 10);
96    }
97
98    /**
99     * Return the log(2) corresponding to the tile width in pixels
100     *
101     * @return 3 (8 pixels) < tile with < 8 (256 pixels)
102     * (by default is given by the square tile size)
103     */
104    public static int getTileWidth_Log2() {
105        final int tileSize = getTileSize_Log2();
106        return getInteger("sun.java2d.renderer.tileWidth_log2", tileSize, 3, 10);
107    }
108
109    /**
110     * Return the log(2) corresponding to the block size in pixels
111     *
112     * @return 3 (8 pixels) < block size < 8 (256 pixels)
113     * (5 by default ie 32 pixels)
114     */
115    public static int getBlockSize_Log2() {
116        return getInteger("sun.java2d.renderer.blockSize_log2", 5, 3, 8);
117    }
118
119    // RLE / blockFlags settings
120
121    public static boolean isForceRLE() {
122        return getBoolean("sun.java2d.renderer.forceRLE", "false");
123    }
124
125    public static boolean isForceNoRLE() {
126        return getBoolean("sun.java2d.renderer.forceNoRLE", "false");
127    }
128
129    public static boolean isUseTileFlags() {
130        return getBoolean("sun.java2d.renderer.useTileFlags", "true");
131    }
132
133    public static boolean isUseTileFlagsWithHeuristics() {
134        return isUseTileFlags()
135        && getBoolean("sun.java2d.renderer.useTileFlags.useHeuristics", "true");
136    }
137
138    public static int getRLEMinWidth() {
139        return getInteger("sun.java2d.renderer.rleMinWidth", 64, 0, Integer.MAX_VALUE);
140    }
141
142    // optimisation parameters
143
144    public static boolean isUseSimplifier() {
145        return getBoolean("sun.java2d.renderer.useSimplifier", "false");
146    }
147
148    // debugging parameters
149
150    public static boolean isDoStats() {
151        return getBoolean("sun.java2d.renderer.doStats", "false");
152    }
153
154    public static boolean isDoMonitors() {
155        return getBoolean("sun.java2d.renderer.doMonitors", "false");
156    }
157
158    public static boolean isDoChecks() {
159        return getBoolean("sun.java2d.renderer.doChecks", "false");
160    }
161
162    // logging parameters
163
164    public static boolean isLoggingEnabled() {
165        return getBoolean("sun.java2d.renderer.log", "false");
166    }
167
168    public static boolean isUseLogger() {
169        return getBoolean("sun.java2d.renderer.useLogger", "false");
170    }
171
172    public static boolean isLogCreateContext() {
173        return getBoolean("sun.java2d.renderer.logCreateContext", "false");
174    }
175
176    public static boolean isLogUnsafeMalloc() {
177        return getBoolean("sun.java2d.renderer.logUnsafeMalloc", "false");
178    }
179
180    // quality settings
181
182    public static float getCubicDecD2() {
183        return getFloat("sun.java2d.renderer.cubic_dec_d2", 1.0f, 0.01f, 4.0f);
184    }
185
186    public static float getCubicIncD1() {
187        return getFloat("sun.java2d.renderer.cubic_inc_d1", 0.4f, 0.01f, 2.0f);
188    }
189
190    public static float getQuadDecD2() {
191        return getFloat("sun.java2d.renderer.quad_dec_d2", 0.5f, 0.01f, 4.0f);
192    }
193
194    // system property utilities
195    static boolean getBoolean(final String key, final String def) {
196        return Boolean.valueOf(AccessController.doPrivileged(
197                  new GetPropertyAction(key, def)));
198    }
199
200    static int getInteger(final String key, final int def,
201                                 final int min, final int max)
202    {
203        final String property = AccessController.doPrivileged(
204                                    new GetPropertyAction(key));
205
206        int value = def;
207        if (property != null) {
208            try {
209                value = Integer.decode(property);
210            } catch (NumberFormatException e) {
211                logInfo("Invalid integer value for " + key + " = " + property);
212            }
213        }
214
215        // check for invalid values
216        if ((value < min) || (value > max)) {
217            logInfo("Invalid value for " + key + " = " + value
218                    + "; expected value in range[" + min + ", " + max + "] !");
219            value = def;
220        }
221        return value;
222    }
223
224    static int align(final int val, final int norm) {
225        final int ceil = FloatMath.ceil_int( ((float) val) / norm);
226        return ceil * norm;
227    }
228
229    public static double getDouble(final String key, final double def,
230                                   final double min, final double max)
231    {
232        double value = def;
233        final String property = AccessController.doPrivileged(
234                                    new GetPropertyAction(key));
235
236        if (property != null) {
237            try {
238                value = Double.parseDouble(property);
239            } catch (NumberFormatException nfe) {
240                logInfo("Invalid value for " + key + " = " + property + " !");
241            }
242        }
243        // check for invalid values
244        if (value < min || value > max) {
245            logInfo("Invalid value for " + key + " = " + value
246                    + "; expect value in range[" + min + ", " + max + "] !");
247            value = def;
248        }
249        return value;
250    }
251
252    public static float getFloat(final String key, final float def,
253                                 final float min, final float max)
254    {
255        return (float)getDouble(key, def, min, max);
256    }
257}
258