History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/SplashScreen.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/SplashScreen.java+400−0
@@ -0,0 +1,400 @@
1+/*
2+ * Copyright (c) 2005, 2010, 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+package java.awt;
26+
27+import java.io.IOException;
28+import java.awt.image.*;
29+import java.net.URL;
30+import java.net.URLConnection;
31+import java.io.File;
32+import sun.util.logging.PlatformLogger;
33+import sun.awt.image.SunWritableRaster;
34+
35+/**
36+ * The splash screen can be displayed at application startup, before the
37+ * Java Virtual Machine (JVM) starts. The splash screen is displayed as an
38+ * undecorated window containing an image. You can use GIF, JPEG, or PNG files
39+ * for the image. Animation is supported for the GIF format, while transparency
40+ * is supported both for GIF and PNG. The window is positioned at the center
41+ * of the screen. The position on multi-monitor systems is not specified. It is
42+ * platform and implementation dependent. The splash screen window is closed
43+ * automatically as soon as the first window is displayed by Swing/AWT (may be
44+ * also closed manually using the Java API, see below).
45+ * <P>
46+ * If your application is packaged in a jar file, you can use the
47+ * "SplashScreen-Image" option in a manifest file to show a splash screen.
48+ * Place the image in the jar archive and specify the path in the option.
49+ * The path should not have a leading slash.
50+ * <BR>
51+ * For example, in the <code>manifest.mf</code> file:
52+ * <PRE>
53+ * Manifest-Version: 1.0
54+ * Main-Class: Test
55+ * SplashScreen-Image: filename.gif
56+ * </PRE>
57+ * <P>
58+ * If the Java implementation provides the command-line interface and you run
59+ * your application by using the command line or a shortcut, use the Java
60+ * application launcher option to show a splash screen. The Oracle reference
61+ * implementation allows you to specify the splash screen image location with
62+ * the {@code -splash:} option.
63+ * <BR>
64+ * For example:
65+ * <PRE>
66+ * java -splash:filename.gif Test
67+ * </PRE>
68+ * The command line interface has higher precedence over the manifest
69+ * setting.
70+ * <p>
71+ * The splash screen will be displayed as faithfully as possible to present the
72+ * whole splash screen image given the limitations of the target platform and
73+ * display.
74+ * <p>
75+ * It is implied that the specified image is presented on the screen "as is",
76+ * i.e. preserving the exact color values as specified in the image file. Under
77+ * certain circumstances, though, the presented image may differ, e.g. when
78+ * applying color dithering to present a 32 bits per pixel (bpp) image on a 16
79+ * or 8 bpp screen. The native platform display configuration may also affect
80+ * the colors of the displayed image (e.g. color profiles, etc.)
81+ * <p>
82+ * The {@code SplashScreen} class provides the API for controlling the splash
83+ * screen. This class may be used to close the splash screen, change the splash
84+ * screen image, get the splash screen native window position/size, and paint
85+ * in the splash screen. It cannot be used to create the splash screen. You
86+ * should use the options provided by the Java implementation for that.
87+ * <p>
88+ * This class cannot be instantiated. Only a single instance of this class
89+ * can exist, and it may be obtained by using the {@link #getSplashScreen()}
90+ * static method. In case the splash screen has not been created at
91+ * application startup via the command line or manifest file option,
92+ * the <code>getSplashScreen</code> method returns <code>null</code>.
93+ *
94+ * @author Oleg Semenov
95+ * @since 1.6
96+ */
97+public final class SplashScreen {
98+
99+ SplashScreen(long ptr) { // non-public constructor
100+ splashPtr = ptr;
101+ }
102+
103+ /**
104+ * Returns the {@code SplashScreen} object used for
105+ * Java startup splash screen control on systems that support display.
106+ *
107+ * @throws UnsupportedOperationException if the splash screen feature is not
108+ * supported by the current toolkit
109+ * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
110+ * returns true
111+ * @return the {@link SplashScreen} instance, or <code>null</code> if there is
112+ * none or it has already been closed
113+ */
114+ public static SplashScreen getSplashScreen() {
115+ synchronized (SplashScreen.class) {
116+ if (GraphicsEnvironment.isHeadless()) {
117+ throw new HeadlessException();
118+ }
119+ // SplashScreen class is now a singleton
120+ if (!wasClosed && theInstance == null) {
121+ java.security.AccessController.doPrivileged(
122+ new sun.security.action.LoadLibraryAction("splashscreen"));
123+ long ptr = _getInstance();
124+ if (ptr != 0 && _isVisible(ptr)) {
125+ theInstance = new SplashScreen(ptr);
126+ }
127+ }
128+ return theInstance;
129+ }
130+ }
131+
132+ /**
133+ * Changes the splash screen image. The new image is loaded from the
134+ * specified URL; GIF, JPEG and PNG image formats are supported.
135+ * The method returns after the image has finished loading and the window
136+ * has been updated.
137+ * The splash screen window is resized according to the size of
138+ * the image and is centered on the screen.
139+ *
140+ * @param imageURL the non-<code>null</code> URL for the new
141+ * splash screen image
142+ * @throws NullPointerException if {@code imageURL} is <code>null</code>
143+ * @throws IOException if there was an error while loading the image
144+ * @throws IllegalStateException if the splash screen has already been
145+ * closed
146+ */
147+ public void setImageURL(URL imageURL) throws NullPointerException, IOException, IllegalStateException {
148+ checkVisible();
149+ URLConnection connection = imageURL.openConnection();
150+ connection.connect();
151+ int length = connection.getContentLength();
152+ java.io.InputStream stream = connection.getInputStream();
153+ byte[] buf = new byte[length];
154+ int off = 0;
155+ while(true) {
156+ // check for available data
157+ int available = stream.available();
158+ if (available <= 0) {
159+ // no data available... well, let's try reading one byte
160+ // we'll see what happens then
161+ available = 1;
162+ }
163+ // check for enough room in buffer, realloc if needed
164+ // the buffer always grows in size 2x minimum
165+ if (off + available > length) {
166+ length = off*2;
167+ if (off + available > length) {
168+ length = available+off;
169+ }
170+ byte[] oldBuf = buf;
171+ buf = new byte[length];
172+ System.arraycopy(oldBuf, 0, buf, 0, off);
173+ }
174+ // now read the data
175+ int result = stream.read(buf, off, available);
176+ if (result < 0) {
177+ break;
178+ }
179+ off += result;
180+ }
181+ synchronized(SplashScreen.class) {
182+ checkVisible();
183+ if (!_setImageData(splashPtr, buf)) {
184+ throw new IOException("Bad image format or i/o error when loading image");
185+ }
186+ this.imageURL = imageURL;
187+ }
188+ }
189+
190+ private void checkVisible() {
191+ if (!isVisible()) {
192+ throw new IllegalStateException("no splash screen available");
193+ }
194+ }
195+ /**
196+ * Returns the current splash screen image.
197+ *
198+ * @return URL for the current splash screen image file
199+ * @throws IllegalStateException if the splash screen has already been closed
200+ */
201+ public URL getImageURL() throws IllegalStateException {
202+ synchronized (SplashScreen.class) {
203+ checkVisible();
204+ if (imageURL == null) {
205+ try {
206+ String fileName = _getImageFileName(splashPtr);
207+ String jarName = _getImageJarName(splashPtr);
208+ if (fileName != null) {
209+ if (jarName != null) {
210+ imageURL = new URL("jar:"+(new File(jarName).toURL().toString())+"!/"+fileName);
211+ } else {
212+ imageURL = new File(fileName).toURL();
213+ }
214+ }
215+ }
216+ catch(java.net.MalformedURLException e) {
217+ if (log.isLoggable(PlatformLogger.FINE)) {
218+ log.fine("MalformedURLException caught in the getImageURL() method", e);
219+ }
220+ }
221+ }
222+ return imageURL;
223+ }
224+ }
225+
226+ /**
227+ * Returns the bounds of the splash screen window as a {@link Rectangle}.
228+ * This may be useful if, for example, you want to replace the splash
229+ * screen with your window at the same location.
230+ * <p>
231+ * You cannot control the size or position of the splash screen.
232+ * The splash screen size is adjusted automatically when the image changes.
233+ * <p>
234+ * The image may contain transparent areas, and thus the reported bounds may
235+ * be larger than the visible splash screen image on the screen.
236+ *
237+ * @return a {@code Rectangle} containing the splash screen bounds
238+ * @throws IllegalStateException if the splash screen has already been closed
239+ */
240+ public Rectangle getBounds() throws IllegalStateException {
241+ synchronized (SplashScreen.class) {
242+ checkVisible();
243+ return _getBounds(splashPtr);
244+ }
245+ }
246+
247+ /**
248+ * Returns the size of the splash screen window as a {@link Dimension}.
249+ * This may be useful if, for example,
250+ * you want to draw on the splash screen overlay surface.
251+ * <p>
252+ * You cannot control the size or position of the splash screen.
253+ * The splash screen size is adjusted automatically when the image changes.
254+ * <p>
255+ * The image may contain transparent areas, and thus the reported size may
256+ * be larger than the visible splash screen image on the screen.
257+ *
258+ * @return a {@link Dimension} object indicating the splash screen size
259+ * @throws IllegalStateException if the splash screen has already been closed
260+ */
261+ public Dimension getSize() throws IllegalStateException {
262+ return getBounds().getSize();
263+ }
264+
265+ /**
266+ * Creates a graphics context (as a {@link Graphics2D} object) for the splash
267+ * screen overlay image, which allows you to draw over the splash screen.
268+ * Note that you do not draw on the main image but on the image that is
269+ * displayed over the main image using alpha blending. Also note that drawing
270+ * on the overlay image does not necessarily update the contents of splash
271+ * screen window. You should call {@code update()} on the
272+ * <code>SplashScreen</code> when you want the splash screen to be
273+ * updated immediately.
274+ * <p>
275+ * The pixel (0, 0) in the coordinate space of the graphics context
276+ * corresponds to the origin of the splash screen native window bounds (see
277+ * {@link #getBounds()}).
278+ *
279+ * @return graphics context for the splash screen overlay surface
280+ * @throws IllegalStateException if the splash screen has already been closed
281+ */
282+ public Graphics2D createGraphics() throws IllegalStateException {
283+ synchronized (SplashScreen.class) {
284+ if (image==null) {
285+ Dimension dim = getSize();
286+ image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
287+ }
288+ return image.createGraphics();
289+ }
290+ }
291+
292+ /**
293+ * Updates the splash window with current contents of the overlay image.
294+ *
295+ * @throws IllegalStateException if the overlay image does not exist;
296+ * for example, if {@code createGraphics} has never been called,
297+ * or if the splash screen has already been closed
298+ */
299+ public void update() throws IllegalStateException {
300+ BufferedImage image;
301+ synchronized (SplashScreen.class) {
302+ checkVisible();
303+ image = this.image;
304+ }
305+ if (image == null) {
306+ throw new IllegalStateException("no overlay image available");
307+ }
308+ DataBuffer buf = image.getRaster().getDataBuffer();
309+ if (!(buf instanceof DataBufferInt)) {
310+ throw new AssertionError("Overlay image DataBuffer is of invalid type == "+buf.getClass().getName());
311+ }
312+ int numBanks = buf.getNumBanks();
313+ if (numBanks!=1) {
314+ throw new AssertionError("Invalid number of banks =="+numBanks+" in overlay image DataBuffer");
315+ }
316+ if (!(image.getSampleModel() instanceof SinglePixelPackedSampleModel)) {
317+ throw new AssertionError("Overlay image has invalid sample model == "+image.getSampleModel().getClass().getName());
318+ }
319+ SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)image.getSampleModel();
320+ int scanlineStride = sm.getScanlineStride();
321+ Rectangle rect = image.getRaster().getBounds();
322+ // Note that we steal the data array here, but just for reading
323+ // so we do not need to mark the DataBuffer dirty...
324+ int[] data = SunWritableRaster.stealData((DataBufferInt)buf, 0);
325+ synchronized(SplashScreen.class) {
326+ checkVisible();
327+ _update(splashPtr, data, rect.x, rect.y, rect.width, rect.height, scanlineStride);
328+ }
329+ }
330+
331+ /**
332+ * Hides the splash screen, closes the window, and releases all associated
333+ * resources.
334+ *
335+ * @throws IllegalStateException if the splash screen has already been closed
336+ */
337+ public void close() throws IllegalStateException {
338+ synchronized (SplashScreen.class) {
339+ checkVisible();
340+ _close(splashPtr);
341+ image = null;
342+ SplashScreen.markClosed();
343+ }
344+ }
345+
346+ static void markClosed() {
347+ synchronized (SplashScreen.class) {
348+ wasClosed = true;
349+ theInstance = null;
350+ }
351+ }
352+
353+
354+ /**
355+ * Determines whether the splash screen is visible. The splash screen may
356+ * be hidden using {@link #close()}, it is also hidden automatically when
357+ * the first AWT/Swing window is made visible.
358+ * <p>
359+ * Note that the native platform may delay presenting the splash screen
360+ * native window on the screen. The return value of {@code true} for this
361+ * method only guarantees that the conditions to hide the splash screen
362+ * window have not occurred yet.
363+ *
364+ * @return true if the splash screen is visible (has not been closed yet),
365+ * false otherwise
366+ */
367+ public boolean isVisible() {
368+ synchronized (SplashScreen.class) {
369+ return !wasClosed && _isVisible(splashPtr);
370+ }
371+ }
372+
373+ private BufferedImage image; // overlay image
374+
375+ private final long splashPtr; // pointer to native Splash structure
376+ private static boolean wasClosed = false;
377+
378+ private URL imageURL;
379+
380+ /**
381+ * The instance reference for the singleton.
382+ * (<code>null</code> if no instance exists yet.)
383+ *
384+ * @see #getSplashScreen
385+ * @see #close
386+ */
387+ private static SplashScreen theInstance = null;
388+
389+ private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.SplashScreen");
390+
391+ private native static void _update(long splashPtr, int[] data, int x, int y, int width, int height, int scanlineStride);
392+ private native static boolean _isVisible(long splashPtr);
393+ private native static Rectangle _getBounds(long splashPtr);
394+ private native static long _getInstance();
395+ private native static void _close(long splashPtr);
396+ private native static String _getImageFileName(long splashPtr);
397+ private native static String _getImageJarName(long SplashPtr);
398+ private native static boolean _setImageData(long SplashPtr, byte[] data);
399+
400+};