1 /* 2 * Copyright (c) 1997, 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 26 27 package java.awt; 28 29 import java.awt.image.BufferedImage; 30 import java.security.AccessController; 31 import java.util.Locale; 32 33 import sun.font.FontManager; 34 import sun.font.FontManagerFactory; 35 import sun.java2d.HeadlessGraphicsEnvironment; 36 import sun.java2d.SunGraphicsEnvironment; 37 import sun.security.action.GetPropertyAction; 38 39 /** 40 * 41 * The <code>GraphicsEnvironment</code> class describes the collection 42 * of {@link GraphicsDevice} objects and {@link java.awt.Font} objects 43 * available to a Java(tm) application on a particular platform. 44 * The resources in this <code>GraphicsEnvironment</code> might be local 45 * or on a remote machine. <code>GraphicsDevice</code> objects can be 46 * screens, printers or image buffers and are the destination of 47 * {@link Graphics2D} drawing methods. Each <code>GraphicsDevice</code> 48 * has a number of {@link GraphicsConfiguration} objects associated with 49 * it. These objects specify the different configurations in which the 50 * <code>GraphicsDevice</code> can be used. 51 * @see GraphicsDevice 52 * @see GraphicsConfiguration 53 */ 54 55 public abstract class GraphicsEnvironment { 56 private static GraphicsEnvironment localEnv; 57 58 /** 59 * The headless state of the Toolkit and GraphicsEnvironment 60 */ 61 private static Boolean headless; 62 63 /** 64 * The headless state assumed by default 65 */ 66 private static Boolean defaultHeadless; 67 68 /** 69 * This is an abstract class and cannot be instantiated directly. 70 * Instances must be obtained from a suitable factory or query method. 71 */ 72 protected GraphicsEnvironment() { 73 } 74 75 /** 76 * Returns the local <code>GraphicsEnvironment</code>. 77 * @return the local <code>GraphicsEnvironment</code> 78 */ 79 public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() { 80 if (localEnv == null) { 81 localEnv = createGE(); 82 } 83 84 return localEnv; 85 } 86 87 /** 88 * Creates and returns the GraphicsEnvironment, according to the 89 * system property 'java.awt.graphicsenv'. 90 * 91 * @return the graphics environment 92 */ 93 private static GraphicsEnvironment createGE() { 94 GraphicsEnvironment ge; 95 String nm = AccessController.doPrivileged(new GetPropertyAction("java.awt.graphicsenv", null)); 96 try { 97 // long t0 = System.currentTimeMillis(); 98 Class geCls; 99 try { 100 // First we try if the bootclassloader finds the requested 101 // class. This way we can avoid to run in a privileged block. 102 geCls = Class.forName(nm); 103 } catch (ClassNotFoundException ex) { 104 // If the bootclassloader fails, we try again with the 105 // application classloader. 106 ClassLoader cl = ClassLoader.getSystemClassLoader(); 107 geCls = Class.forName(nm, true, cl); 108 } 109 ge = (GraphicsEnvironment) geCls.newInstance(); 110 // long t1 = System.currentTimeMillis(); 111 // System.out.println("GE creation took " + (t1-t0)+ "ms."); 112 if (isHeadless()) { 113 ge = new HeadlessGraphicsEnvironment(ge); 114 } 115 } catch (ClassNotFoundException e) { 116 throw new Error("Could not find class: "+nm); 117 } catch (InstantiationException e) { 118 throw new Error("Could not instantiate Graphics Environment: " 119 + nm); 120 } catch (IllegalAccessException e) { 121 throw new Error ("Could not access Graphics Environment: " 122 + nm); 123 } 124 return ge; 125 } 126 127 /** 128 * Tests whether or not a display, keyboard, and mouse can be 129 * supported in this environment. If this method returns true, 130 * a HeadlessException is thrown from areas of the Toolkit 131 * and GraphicsEnvironment that are dependent on a display, 132 * keyboard, or mouse. 133 * @return <code>true</code> if this environment cannot support 134 * a display, keyboard, and mouse; <code>false</code> 135 * otherwise 136 * @see java.awt.HeadlessException 137 * @since 1.4 138 */ 139 public static boolean isHeadless() { 140 return getHeadlessProperty(); 141 } 142 143 /** 144 * @return warning message if headless state is assumed by default; 145 * null otherwise 146 * @since 1.5 147 */ 148 static String getHeadlessMessage() { 149 if (headless == null) { 150 getHeadlessProperty(); // initialize the values 151 } 152 return defaultHeadless != Boolean.TRUE ? null : 153 "\nNo X11 DISPLAY variable was set, " + 154 "but this program performed an operation which requires it."; 155 } 156 157 /** 158 * @return the value of the property "java.awt.headless" 159 * @since 1.4 160 */ 161 private static boolean getHeadlessProperty() { 162 if (headless == null) { 163 java.security.AccessController.doPrivileged( 164 new java.security.PrivilegedAction() { 165 public Object run() { 166 String nm = System.getProperty("java.awt.headless"); 167 168 if (nm == null) { 169 /* No need to ask for DISPLAY when run in a browser */ 170 if (System.getProperty("javaplugin.version") != null) { 171 headless = defaultHeadless = Boolean.FALSE; 172 } else { 173 String osName = System.getProperty("os.name"); 174 headless = defaultHeadless = 175 Boolean.valueOf(("Linux".equals(osName) || 176 "SunOS".equals(osName) || 177 "FreeBSD".equals(osName) || 178 "NetBSD".equals(osName) || 179 "OpenBSD".equals(osName)) && 180 (System.getenv("DISPLAY") == null)); 181 } 182 } else if (nm.equals("true")) { 183 headless = Boolean.TRUE; 184 } else { 185 headless = Boolean.FALSE; 186 } 187 return null; 188 } 189 } 190 ); 191 } 192 return headless.booleanValue(); 193 } 194 195 /** 196 * Check for headless state and throw HeadlessException if headless 197 * @since 1.4 198 */ 199 static void checkHeadless() throws HeadlessException { 200 if (isHeadless()) { 201 throw new HeadlessException(); 202 } 203 } 204 205 /** 206 * Returns whether or not a display, keyboard, and mouse can be 207 * supported in this graphics environment. If this returns true, 208 * <code>HeadlessException</code> will be thrown from areas of the 209 * graphics environment that are dependent on a display, keyboard, or 210 * mouse. 211 * @return <code>true</code> if a display, keyboard, and mouse 212 * can be supported in this environment; <code>false</code> 213 * otherwise 214 * @see java.awt.HeadlessException 215 * @see #isHeadless 216 * @since 1.4 217 */ 218 public boolean isHeadlessInstance() { 219 // By default (local graphics environment), simply check the 220 // headless property. 221 return getHeadlessProperty(); 222 } 223 224 /** 225 * Returns an array of all of the screen <code>GraphicsDevice</code> 226 * objects. 227 * @return an array containing all the <code>GraphicsDevice</code> 228 * objects that represent screen devices 229 * @exception HeadlessException if isHeadless() returns true 230 * @see #isHeadless() 231 */ 232 public abstract GraphicsDevice[] getScreenDevices() 233 throws HeadlessException; 234 235 /** 236 * Returns the default screen <code>GraphicsDevice</code>. 237 * @return the <code>GraphicsDevice</code> that represents the 238 * default screen device 239 * @exception HeadlessException if isHeadless() returns true 240 * @see #isHeadless() 241 */ 242 public abstract GraphicsDevice getDefaultScreenDevice() 243 throws HeadlessException; 244 245 /** 246 * Returns a <code>Graphics2D</code> object for rendering into the 247 * specified {@link BufferedImage}. 248 * @param img the specified <code>BufferedImage</code> 249 * @return a <code>Graphics2D</code> to be used for rendering into 250 * the specified <code>BufferedImage</code> 251 * @throws NullPointerException if <code>img</code> is null 252 */ 253 public abstract Graphics2D createGraphics(BufferedImage img); 254 255 /** 256 * Returns an array containing a one-point size instance of all fonts 257 * available in this <code>GraphicsEnvironment</code>. Typical usage 258 * would be to allow a user to select a particular font. Then, the 259 * application can size the font and set various font attributes by 260 * calling the <code>deriveFont</code> method on the choosen instance. 261 * <p> 262 * This method provides for the application the most precise control 263 * over which <code>Font</code> instance is used to render text. 264 * If a font in this <code>GraphicsEnvironment</code> has multiple 265 * programmable variations, only one 266 * instance of that <code>Font</code> is returned in the array, and 267 * other variations must be derived by the application. 268 * <p> 269 * If a font in this environment has multiple programmable variations, 270 * such as Multiple-Master fonts, only one instance of that font is 271 * returned in the <code>Font</code> array. The other variations 272 * must be derived by the application. 273 * 274 * @return an array of <code>Font</code> objects 275 * @see #getAvailableFontFamilyNames 276 * @see java.awt.Font 277 * @see java.awt.Font#deriveFont 278 * @see java.awt.Font#getFontName 279 * @since 1.2 280 */ 281 public abstract Font[] getAllFonts(); 282 283 /** 284 * Returns an array containing the names of all font families in this 285 * <code>GraphicsEnvironment</code> localized for the default locale, 286 * as returned by <code>Locale.getDefault()</code>. 287 * <p> 288 * Typical usage would be for presentation to a user for selection of 289 * a particular family name. An application can then specify this name 290 * when creating a font, in conjunction with a style, such as bold or 291 * italic, giving the font system flexibility in choosing its own best 292 * match among multiple fonts in the same font family. 293 * 294 * @return an array of <code>String</code> containing font family names 295 * localized for the default locale, or a suitable alternative 296 * name if no name exists for this locale. 297 * @see #getAllFonts 298 * @see java.awt.Font 299 * @see java.awt.Font#getFamily 300 * @since 1.2 301 */ 302 public abstract String[] getAvailableFontFamilyNames(); 303 304 /** 305 * Returns an array containing the names of all font families in this 306 * <code>GraphicsEnvironment</code> localized for the specified locale. 307 * <p> 308 * Typical usage would be for presentation to a user for selection of 309 * a particular family name. An application can then specify this name 310 * when creating a font, in conjunction with a style, such as bold or 311 * italic, giving the font system flexibility in choosing its own best 312 * match among multiple fonts in the same font family. 313 * 314 * @param l a {@link Locale} object that represents a 315 * particular geographical, political, or cultural region. 316 * Specifying <code>null</code> is equivalent to 317 * specifying <code>Locale.getDefault()</code>. 318 * @return an array of <code>String</code> containing font family names 319 * localized for the specified <code>Locale</code>, or a 320 * suitable alternative name if no name exists for the specified locale. 321 * @see #getAllFonts 322 * @see java.awt.Font 323 * @see java.awt.Font#getFamily 324 * @since 1.2 325 */ 326 public abstract String[] getAvailableFontFamilyNames(Locale l); 327 328 /** 329 * Registers a <i>created</i> <code>Font</code>in this 330 * <code>GraphicsEnvironment</code>. 331 * A created font is one that was returned from calling 332 * {@link Font#createFont}, or derived from a created font by 333 * calling {@link Font#deriveFont}. 334 * After calling this method for such a font, it is available to 335 * be used in constructing new <code>Font</code>s by name or family name, 336 * and is enumerated by {@link #getAvailableFontFamilyNames} and 337 * {@link #getAllFonts} within the execution context of this 338 * application or applet. This means applets cannot register fonts in 339 * a way that they are visible to other applets. 340 * <p> 341 * Reasons that this method might not register the font and therefore 342 * return <code>false</code> are: 343 * <ul> 344 * <li>The font is not a <i>created</i> <code>Font</code>. 345 * <li>The font conflicts with a non-created <code>Font</code> already 346 * in this <code>GraphicsEnvironment</code>. For example if the name 347 * is that of a system font, or a logical font as described in the 348 * documentation of the {@link Font} class. It is implementation dependent 349 * whether a font may also conflict if it has the same family name 350 * as a system font. 351 * <p>Notice that an application can supersede the registration 352 * of an earlier created font with a new one. 353 * </ul> 354 * @return true if the <code>font</code> is successfully 355 * registered in this <code>GraphicsEnvironment</code>. 356 * @throws NullPointerException if <code>font</code> is null 357 * @since 1.6 358 */ 359 public boolean registerFont(Font font) { 360 if (font == null) { 361 throw new NullPointerException("font cannot be null."); 362 } 363 FontManager fm = FontManagerFactory.getInstance(); 364 return fm.registerFont(font); 365 } 366 367 /** 368 * Indicates a preference for locale-specific fonts in the mapping of 369 * logical fonts to physical fonts. Calling this method indicates that font 370 * rendering should primarily use fonts specific to the primary writing 371 * system (the one indicated by the default encoding and the initial 372 * default locale). For example, if the primary writing system is 373 * Japanese, then characters should be rendered using a Japanese font 374 * if possible, and other fonts should only be used for characters for 375 * which the Japanese font doesn't have glyphs. 376 * <p> 377 * The actual change in font rendering behavior resulting from a call 378 * to this method is implementation dependent; it may have no effect at 379 * all, or the requested behavior may already match the default behavior. 380 * The behavior may differ between font rendering in lightweight 381 * and peered components. Since calling this method requests a 382 * different font, clients should expect different metrics, and may need 383 * to recalculate window sizes and layout. Therefore this method should 384 * be called before user interface initialisation. 385 * @since 1.5 386 */ 387 public void preferLocaleFonts() { 388 FontManager fm = FontManagerFactory.getInstance(); 389 fm.preferLocaleFonts(); 390 } 391 392 /** 393 * Indicates a preference for proportional over non-proportional (e.g. 394 * dual-spaced CJK fonts) fonts in the mapping of logical fonts to 395 * physical fonts. If the default mapping contains fonts for which 396 * proportional and non-proportional variants exist, then calling 397 * this method indicates the mapping should use a proportional variant. 398 * <p> 399 * The actual change in font rendering behavior resulting from a call to 400 * this method is implementation dependent; it may have no effect at all. 401 * The behavior may differ between font rendering in lightweight and 402 * peered components. Since calling this method requests a 403 * different font, clients should expect different metrics, and may need 404 * to recalculate window sizes and layout. Therefore this method should 405 * be called before user interface initialisation. 406 * @since 1.5 407 */ 408 public void preferProportionalFonts() { 409 FontManager fm = FontManagerFactory.getInstance(); 410 fm.preferProportionalFonts(); 411 } 412 413 /** 414 * Returns the Point where Windows should be centered. 415 * It is recommended that centered Windows be checked to ensure they fit 416 * within the available display area using getMaximumWindowBounds(). 417 * @return the point where Windows should be centered 418 * 419 * @exception HeadlessException if isHeadless() returns true 420 * @see #getMaximumWindowBounds 421 * @since 1.4 422 */ 423 public Point getCenterPoint() throws HeadlessException { 424 // Default implementation: return the center of the usable bounds of the 425 // default screen device. 426 Rectangle usableBounds = 427 SunGraphicsEnvironment.getUsableBounds(getDefaultScreenDevice()); 428 return new Point((usableBounds.width / 2) + usableBounds.x, 429 (usableBounds.height / 2) + usableBounds.y); 430 } 431 432 /** 433 * Returns the maximum bounds for centered Windows. 434 * These bounds account for objects in the native windowing system such as 435 * task bars and menu bars. The returned bounds will reside on a single 436 * display with one exception: on multi-screen systems where Windows should 437 * be centered across all displays, this method returns the bounds of the 438 * entire display area. 439 * <p> 440 * To get the usable bounds of a single display, use 441 * <code>GraphicsConfiguration.getBounds()</code> and 442 * <code>Toolkit.getScreenInsets()</code>. 443 * @return the maximum bounds for centered Windows 444 * 445 * @exception HeadlessException if isHeadless() returns true 446 * @see #getCenterPoint 447 * @see GraphicsConfiguration#getBounds 448 * @see Toolkit#getScreenInsets 449 * @since 1.4 450 */ 451 public Rectangle getMaximumWindowBounds() throws HeadlessException { 452 // Default implementation: return the usable bounds of the default screen 453 // device. This is correct for Microsoft Windows and non-Xinerama X11. 454 return SunGraphicsEnvironment.getUsableBounds(getDefaultScreenDevice()); 455 } 456 }