001: /*
002: * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.awt;
027:
028: import java.awt.image.BufferedImage;
029: import java.util.Locale;
030: import sun.java2d.HeadlessGraphicsEnvironment;
031: import sun.java2d.SunGraphicsEnvironment;
032:
033: /**
034: *
035: * The <code>GraphicsEnvironment</code> class describes the collection
036: * of {@link GraphicsDevice} objects and {@link java.awt.Font} objects
037: * available to a Java(tm) application on a particular platform.
038: * The resources in this <code>GraphicsEnvironment</code> might be local
039: * or on a remote machine. <code>GraphicsDevice</code> objects can be
040: * screens, printers or image buffers and are the destination of
041: * {@link Graphics2D} drawing methods. Each <code>GraphicsDevice</code>
042: * has a number of {@link GraphicsConfiguration} objects associated with
043: * it. These objects specify the different configurations in which the
044: * <code>GraphicsDevice</code> can be used.
045: * @see GraphicsDevice
046: * @see GraphicsConfiguration
047: * @version 1.74, 06/04/07
048: */
049:
050: public abstract class GraphicsEnvironment {
051: private static GraphicsEnvironment localEnv;
052:
053: /**
054: * The headless state of the Toolkit and GraphicsEnvironment
055: */
056: private static Boolean headless;
057:
058: /**
059: * The headless state assumed by default
060: */
061: private static Boolean defaultHeadless;
062:
063: /**
064: * This is an abstract class and cannot be instantiated directly.
065: * Instances must be obtained from a suitable factory or query method.
066: */
067: protected GraphicsEnvironment() {
068: }
069:
070: /**
071: * Returns the local <code>GraphicsEnvironment</code>.
072: * @return the local <code>GraphicsEnvironment</code>
073: */
074: public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() {
075: if (localEnv == null) {
076: String nm = (String) java.security.AccessController
077: .doPrivileged(new sun.security.action.GetPropertyAction(
078: "java.awt.graphicsenv", null));
079:
080: try {
081: // long t0 = System.currentTimeMillis();
082: localEnv = (GraphicsEnvironment) Class.forName(nm)
083: .newInstance();
084: // long t1 = System.currentTimeMillis();
085: // System.out.println("GE creation took " + (t1-t0)+ "ms.");
086: if (isHeadless()) {
087: localEnv = new HeadlessGraphicsEnvironment(localEnv);
088: }
089: } catch (ClassNotFoundException e) {
090: throw new Error("Could not find class: " + nm);
091: } catch (InstantiationException e) {
092: throw new Error(
093: "Could not instantiate Graphics Environment: "
094: + nm);
095: } catch (IllegalAccessException e) {
096: throw new Error(
097: "Could not access Graphics Environment: " + nm);
098: }
099: }
100:
101: return localEnv;
102: }
103:
104: /**
105: * Tests whether or not a display, keyboard, and mouse can be
106: * supported in this environment. If this method returns true,
107: * a HeadlessException is thrown from areas of the Toolkit
108: * and GraphicsEnvironment that are dependent on a display,
109: * keyboard, or mouse.
110: * @return <code>true</code> if this environment cannot support
111: * a display, keyboard, and mouse; <code>false</code>
112: * otherwise
113: * @see java.awt.HeadlessException
114: * @since 1.4
115: */
116: public static boolean isHeadless() {
117: return getHeadlessProperty();
118: }
119:
120: /**
121: * @return warning message if headless state is assumed by default;
122: * null otherwise
123: * @since 1.5
124: */
125: static String getHeadlessMessage() {
126: if (headless == null) {
127: getHeadlessProperty(); // initialize the values
128: }
129: return defaultHeadless != Boolean.TRUE ? null
130: : "\nNo X11 DISPLAY variable was set, "
131: + "but this program performed an operation which requires it.";
132: }
133:
134: /**
135: * @return the value of the property "java.awt.headless"
136: * @since 1.4
137: */
138: private static boolean getHeadlessProperty() {
139: if (headless == null) {
140: java.security.AccessController
141: .doPrivileged(new java.security.PrivilegedAction() {
142: public Object run() {
143: String nm = System
144: .getProperty("java.awt.headless");
145:
146: if (nm == null) {
147: /* No need to ask for DISPLAY when run in a browser */
148: if (System
149: .getProperty("javaplugin.version") != null) {
150: headless = defaultHeadless = Boolean.FALSE;
151: } else {
152: String osName = System
153: .getProperty("os.name");
154: headless = defaultHeadless = Boolean
155: .valueOf(("Linux"
156: .equals(osName) || "SunOS"
157: .equals(osName))
158: && (System
159: .getenv("DISPLAY") == null));
160: }
161: } else if (nm.equals("true")) {
162: headless = Boolean.TRUE;
163: } else {
164: headless = Boolean.FALSE;
165: }
166: return null;
167: }
168: });
169: }
170: return headless.booleanValue();
171: }
172:
173: /**
174: * Check for headless state and throw HeadlessException if headless
175: * @since 1.4
176: */
177: static void checkHeadless() throws HeadlessException {
178: if (isHeadless()) {
179: throw new HeadlessException();
180: }
181: }
182:
183: /**
184: * Returns whether or not a display, keyboard, and mouse can be
185: * supported in this graphics environment. If this returns true,
186: * <code>HeadlessException</code> will be thrown from areas of the
187: * graphics environment that are dependent on a display, keyboard, or
188: * mouse.
189: * @return <code>true</code> if a display, keyboard, and mouse
190: * can be supported in this environment; <code>false</code>
191: * otherwise
192: * @see java.awt.HeadlessException
193: * @see #isHeadless
194: * @since 1.4
195: */
196: public boolean isHeadlessInstance() {
197: // By default (local graphics environment), simply check the
198: // headless property.
199: return getHeadlessProperty();
200: }
201:
202: /**
203: * Returns an array of all of the screen <code>GraphicsDevice</code>
204: * objects.
205: * @return an array containing all the <code>GraphicsDevice</code>
206: * objects that represent screen devices
207: * @exception HeadlessException if isHeadless() returns true
208: * @see #isHeadless()
209: */
210: public abstract GraphicsDevice[] getScreenDevices()
211: throws HeadlessException;
212:
213: /**
214: * Returns the default screen <code>GraphicsDevice</code>.
215: * @return the <code>GraphicsDevice</code> that represents the
216: * default screen device
217: * @exception HeadlessException if isHeadless() returns true
218: * @see #isHeadless()
219: */
220: public abstract GraphicsDevice getDefaultScreenDevice()
221: throws HeadlessException;
222:
223: /**
224: * Returns a <code>Graphics2D</code> object for rendering into the
225: * specified {@link BufferedImage}.
226: * @param img the specified <code>BufferedImage</code>
227: * @return a <code>Graphics2D</code> to be used for rendering into
228: * the specified <code>BufferedImage</code>
229: * @throws NullPointerException if <code>img</code> is null
230: */
231: public abstract Graphics2D createGraphics(BufferedImage img);
232:
233: /**
234: * Returns an array containing a one-point size instance of all fonts
235: * available in this <code>GraphicsEnvironment</code>. Typical usage
236: * would be to allow a user to select a particular font. Then, the
237: * application can size the font and set various font attributes by
238: * calling the <code>deriveFont</code> method on the choosen instance.
239: * <p>
240: * This method provides for the application the most precise control
241: * over which <code>Font</code> instance is used to render text.
242: * If a font in this <code>GraphicsEnvironment</code> has multiple
243: * programmable variations, only one
244: * instance of that <code>Font</code> is returned in the array, and
245: * other variations must be derived by the application.
246: * <p>
247: * If a font in this environment has multiple programmable variations,
248: * such as Multiple-Master fonts, only one instance of that font is
249: * returned in the <code>Font</code> array. The other variations
250: * must be derived by the application.
251: *
252: * @return an array of <code>Font</code> objects
253: * @see #getAvailableFontFamilyNames
254: * @see java.awt.Font
255: * @see java.awt.Font#deriveFont
256: * @see java.awt.Font#getFontName
257: * @since 1.2
258: */
259: public abstract Font[] getAllFonts();
260:
261: /**
262: * Returns an array containing the names of all font families in this
263: * <code>GraphicsEnvironment</code> localized for the default locale,
264: * as returned by <code>Locale.getDefault()</code>.
265: * <p>
266: * Typical usage would be for presentation to a user for selection of
267: * a particular family name. An application can then specify this name
268: * when creating a font, in conjunction with a style, such as bold or
269: * italic, giving the font system flexibility in choosing its own best
270: * match among multiple fonts in the same font family.
271: *
272: * @return an array of <code>String</code> containing font family names
273: * localized for the default locale, or a suitable alternative
274: * name if no name exists for this locale.
275: * @see #getAllFonts
276: * @see java.awt.Font
277: * @see java.awt.Font#getFamily
278: * @since 1.2
279: */
280: public abstract String[] getAvailableFontFamilyNames();
281:
282: /**
283: * Returns an array containing the names of all font families in this
284: * <code>GraphicsEnvironment</code> localized for the specified locale.
285: * <p>
286: * Typical usage would be for presentation to a user for selection of
287: * a particular family name. An application can then specify this name
288: * when creating a font, in conjunction with a style, such as bold or
289: * italic, giving the font system flexibility in choosing its own best
290: * match among multiple fonts in the same font family.
291: *
292: * @param l a {@link Locale} object that represents a
293: * particular geographical, political, or cultural region.
294: * Specifying <code>null</code> is equivalent to
295: * specifying <code>Locale.getDefault()</code>.
296: * @return an array of <code>String</code> containing font family names
297: * localized for the specified <code>Locale</code>, or a
298: * suitable alternative name if no name exists for the specified locale.
299: * @see #getAllFonts
300: * @see java.awt.Font
301: * @see java.awt.Font#getFamily
302: * @since 1.2
303: */
304: public abstract String[] getAvailableFontFamilyNames(Locale l);
305:
306: /**
307: * Registers a <i>created</i> <code>Font</code>in this
308: * <code>GraphicsEnvironment</code>.
309: * A created font is one that was returned from calling
310: * {@link Font#createFont}, or derived from a created font by
311: * calling {@link Font#deriveFont}.
312: * After calling this method for such a font, it is available to
313: * be used in constructing new <code>Font</code>s by name or family name,
314: * and is enumerated by {@link #getAvailableFontFamilyNames} and
315: * {@link #getAllFonts} within the execution context of this
316: * application or applet. This means applets cannot register fonts in
317: * a way that they are visible to other applets.
318: * <p>
319: * Reasons that this method might not register the font and therefore
320: * return <code>false</code> are:
321: * <ul>
322: * <li>The font is not a <i>created</i> <code>Font</code>.
323: * <li>The font conflicts with a non-created <code>Font</code> already
324: * in this <code>GraphicsEnvironment</code>. For example if the name
325: * is that of a system font, or a logical font as described in the
326: * documentation of the {@link Font} class. It is implementation dependent
327: * whether a font may also conflict if it has the same family name
328: * as a system font.
329: * <p>Notice that an application can supersede the registration
330: * of an earlier created font with a new one.
331: * </ul>
332: * @return true if the <code>font</code> is successfully
333: * registered in this <code>GraphicsEnvironment</code>.
334: * @throws NullPointerException if <code>font</code> is null
335: * @since 1.6
336: */
337: public boolean registerFont(Font font) {
338: if (font == null) {
339: throw new NullPointerException("font cannot be null.");
340: }
341: return sun.font.FontManager.registerFont(font);
342: }
343:
344: /**
345: * Indicates a preference for locale-specific fonts in the mapping of
346: * logical fonts to physical fonts. Calling this method indicates that font
347: * rendering should primarily use fonts specific to the primary writing
348: * system (the one indicated by the default encoding and the initial
349: * default locale). For example, if the primary writing system is
350: * Japanese, then characters should be rendered using a Japanese font
351: * if possible, and other fonts should only be used for characters for
352: * which the Japanese font doesn't have glyphs.
353: * <p>
354: * The actual change in font rendering behavior resulting from a call
355: * to this method is implementation dependent; it may have no effect at
356: * all, or the requested behavior may already match the default behavior.
357: * The behavior may differ between font rendering in lightweight
358: * and peered components. Since calling this method requests a
359: * different font, clients should expect different metrics, and may need
360: * to recalculate window sizes and layout. Therefore this method should
361: * be called before user interface initialisation.
362: * @since 1.5
363: */
364: public void preferLocaleFonts() {
365: sun.font.FontManager.preferLocaleFonts();
366: }
367:
368: /**
369: * Indicates a preference for proportional over non-proportional (e.g.
370: * dual-spaced CJK fonts) fonts in the mapping of logical fonts to
371: * physical fonts. If the default mapping contains fonts for which
372: * proportional and non-proportional variants exist, then calling
373: * this method indicates the mapping should use a proportional variant.
374: * <p>
375: * The actual change in font rendering behavior resulting from a call to
376: * this method is implementation dependent; it may have no effect at all.
377: * The behavior may differ between font rendering in lightweight and
378: * peered components. Since calling this method requests a
379: * different font, clients should expect different metrics, and may need
380: * to recalculate window sizes and layout. Therefore this method should
381: * be called before user interface initialisation.
382: * @since 1.5
383: */
384: public void preferProportionalFonts() {
385: sun.font.FontManager.preferProportionalFonts();
386: }
387:
388: /**
389: * Returns the Point where Windows should be centered.
390: * It is recommended that centered Windows be checked to ensure they fit
391: * within the available display area using getMaximumWindowBounds().
392: * @return the point where Windows should be centered
393: *
394: * @exception HeadlessException if isHeadless() returns true
395: * @see #getMaximumWindowBounds
396: * @since 1.4
397: */
398: public Point getCenterPoint() throws HeadlessException {
399: // Default implementation: return the center of the usable bounds of the
400: // default screen device.
401: Rectangle usableBounds = SunGraphicsEnvironment
402: .getUsableBounds(getDefaultScreenDevice());
403: return new Point((usableBounds.width / 2) + usableBounds.x,
404: (usableBounds.height / 2) + usableBounds.y);
405: }
406:
407: /**
408: * Returns the maximum bounds for centered Windows.
409: * These bounds account for objects in the native windowing system such as
410: * task bars and menu bars. The returned bounds will reside on a single
411: * display with one exception: on multi-screen systems where Windows should
412: * be centered across all displays, this method returns the bounds of the
413: * entire display area.
414: * <p>
415: * To get the usable bounds of a single display, use
416: * <code>GraphicsConfiguration.getBounds()</code> and
417: * <code>Toolkit.getScreenInsets()</code>.
418: * @return the maximum bounds for centered Windows
419: *
420: * @exception HeadlessException if isHeadless() returns true
421: * @see #getCenterPoint
422: * @see GraphicsConfiguration#getBounds
423: * @see Toolkit#getScreenInsets
424: * @since 1.4
425: */
426: public Rectangle getMaximumWindowBounds() throws HeadlessException {
427: // Default implementation: return the usable bounds of the default screen
428: // device. This is correct for Microsoft Windows and non-Xinerama X11.
429: return SunGraphicsEnvironment
430: .getUsableBounds(getDefaultScreenDevice());
431: }
432: }
|