1 /* 2 * Copyright 1997-2008 Sun Microsystems, Inc. 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package sun.java2d; 27 28 import java.awt.Color; 29 import java.awt.Font; 30 import java.awt.Graphics2D; 31 import java.awt.GraphicsConfiguration; 32 import java.awt.GraphicsDevice; 33 import java.awt.GraphicsEnvironment; 34 import java.awt.Insets; 35 import java.awt.Rectangle; 36 import java.awt.Toolkit; 37 import java.awt.font.TextAttribute; 38 import java.awt.image.BufferedImage; 39 import java.awt.peer.ComponentPeer; 40 import java.io.BufferedReader; 41 import java.io.File; 42 import java.io.FileInputStream; 43 import java.io.FilenameFilter; 44 import java.io.InputStreamReader; 45 import java.io.IOException; 46 import java.text.AttributedCharacterIterator; 47 import java.util.ArrayList; 48 import java.util.HashSet; 49 import java.util.Iterator; 50 import java.util.Locale; 51 import java.util.Map; 52 import java.util.NoSuchElementException; 53 import java.util.Set; 54 import java.util.StringTokenizer; 55 import java.util.TreeMap; 56 import java.util.Vector; 57 import java.util.concurrent.ConcurrentHashMap; 58 import java.util.logging.Level; 59 import java.util.logging.Logger; 60 import sun.awt.AppContext; 61 import sun.awt.DisplayChangedListener; 62 import sun.awt.FontConfiguration; 63 import sun.awt.SunDisplayChanger; 64 import sun.font.CompositeFontDescriptor; 65 import sun.font.Font2D; 66 import sun.font.FontManager; 67 import sun.font.FontManagerFactory; 68 import sun.font.FontManagerForSGE; 69 import sun.font.NativeFont; 70 71 /** 72 * This is an implementation of a GraphicsEnvironment object for the 73 * default local GraphicsEnvironment. 74 * 75 * @see GraphicsDevice 76 * @see GraphicsConfiguration 77 */ 78 public abstract class SunGraphicsEnvironment extends GraphicsEnvironment 79 implements DisplayChangedListener { 80 81 public static boolean isOpenSolaris; 82 private static Font defaultFont; 83 protected static Logger logger = null; 84 85 public SunGraphicsEnvironment() { 86 java.security.AccessController.doPrivileged( 87 new java.security.PrivilegedAction() { 88 public Object run() { 89 String version = System.getProperty("os.version", "0.0"); 90 try { 91 float ver = Float.parseFloat(version); 92 if (ver > 5.10f) { 93 File f = new File("/etc/release"); 94 FileInputStream fis = new FileInputStream(f); 95 InputStreamReader isr 96 = new InputStreamReader(fis, "ISO-8859-1"); 97 BufferedReader br = new BufferedReader(isr); 98 String line = br.readLine(); 99 if (line.indexOf("OpenSolaris") >= 0) { 100 isOpenSolaris = true; 101 } 102 fis.close(); 103 } 104 } catch (Exception e) { 105 } 106 107 /* Establish the default font to be used by SG2D etc */ 108 defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); 109 110 return null; 111 } 112 }); 113 } 114 115 protected GraphicsDevice[] screens; 116 117 /** 118 * Returns an array of all of the screen devices. 119 */ 120 public synchronized GraphicsDevice[] getScreenDevices() { 121 GraphicsDevice[] ret = screens; 122 if (ret == null) { 123 int num = getNumScreens(); 124 ret = new GraphicsDevice[num]; 125 for (int i = 0; i < num; i++) { 126 ret[i] = makeScreenDevice(i); 127 } 128 screens = ret; 129 } 130 return ret; 131 } 132 133 /** 134 * Returns the number of screen devices of this graphics environment. 135 * 136 * @return the number of screen devices of this graphics environment 137 */ 138 protected abstract int getNumScreens(); 139 140 /** 141 * Create and return the screen device with the specified number. The 142 * device with number <code>0</code> will be the default device (returned 143 * by {@link #getDefaultScreenDevice()}. 144 * 145 * @param screennum the number of the screen to create 146 * 147 * @return the created screen device 148 */ 149 protected abstract GraphicsDevice makeScreenDevice(int screennum); 150 151 /** 152 * Returns the default screen graphics device. 153 */ 154 public GraphicsDevice getDefaultScreenDevice() { 155 return getScreenDevices()[0]; 156 } 157 158 /** 159 * Returns a Graphics2D object for rendering into the 160 * given BufferedImage. 161 * @throws NullPointerException if BufferedImage argument is null 162 */ 163 public Graphics2D createGraphics(BufferedImage img) { 164 if (img == null) { 165 throw new NullPointerException("BufferedImage cannot be null"); 166 } 167 SurfaceData sd = SurfaceData.getPrimarySurfaceData(img); 168 return new SunGraphics2D(sd, Color.white, Color.black, defaultFont); 169 } 170 171 private static FontManagerForSGE getFontManagerForSGE() { 172 FontManager fm = FontManagerFactory.getInstance(); 173 return (FontManagerForSGE) fm; 174 } 175 /** 176 * Returns all fonts available in this environment. 177 */ 178 public Font[] getAllFonts() { 179 FontManagerForSGE fm = getFontManagerForSGE(); 180 Font[] installedFonts = fm.getAllInstalledFonts(); 181 Font[] created = fm.getCreatedFonts(); 182 if (created == null || created.length == 0) { 183 return installedFonts; 184 } else { 185 int newlen = installedFonts.length + created.length; 186 Font [] fonts = java.util.Arrays.copyOf(installedFonts, newlen); 187 System.arraycopy(created, 0, fonts, 188 installedFonts.length, created.length); 189 return fonts; 190 } 191 } 192 193 public String[] getAvailableFontFamilyNames(Locale requestedLocale) { 194 FontManagerForSGE fm = getFontManagerForSGE(); 195 String[] installed = fm.getInstalledFontFamilyNames(requestedLocale); 196 /* Use a new TreeMap as used in getInstalledFontFamilyNames 197 * and insert all the keys in lower case, so that the sort order 198 * is the same as the installed families. This preserves historical 199 * behaviour and inserts new families in the right place. 200 * It would have been marginally more efficient to directly obtain 201 * the tree map and just insert new entries, but not so much as 202 * to justify the extra internal interface. 203 */ 204 TreeMap<String, String> map = fm.getCreatedFontFamilyNames(); 205 if (map == null || map.size() == 0) { 206 return installed; 207 } else { 208 for (int i=0; i<installed.length; i++) { 209 map.put(installed[i].toLowerCase(requestedLocale), 210 installed[i]); 211 } 212 String[] retval = new String[map.size()]; 213 Object [] keyNames = map.keySet().toArray(); 214 for (int i=0; i < keyNames.length; i++) { 215 retval[i] = (String)map.get(keyNames[i]); 216 } 217 return retval; 218 } 219 } 220 221 public String[] getAvailableFontFamilyNames() { 222 return getAvailableFontFamilyNames(Locale.getDefault()); 223 } 224 225 /** 226 * Return the bounds of a GraphicsDevice, less its screen insets. 227 * See also java.awt.GraphicsEnvironment.getUsableBounds(); 228 */ 229 public static Rectangle getUsableBounds(GraphicsDevice gd) { 230 GraphicsConfiguration gc = gd.getDefaultConfiguration(); 231 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); 232 Rectangle usableBounds = gc.getBounds(); 233 234 usableBounds.x += insets.left; 235 usableBounds.y += insets.top; 236 usableBounds.width -= (insets.left + insets.right); 237 usableBounds.height -= (insets.top + insets.bottom); 238 239 return usableBounds; 240 } 241 242 /** 243 * From the DisplayChangedListener interface; called 244 * when the display mode has been changed. 245 */ 246 public void displayChanged() { 247 // notify screens in device array to do display update stuff 248 for (GraphicsDevice gd : getScreenDevices()) { 249 if (gd instanceof DisplayChangedListener) { 250 ((DisplayChangedListener) gd).displayChanged(); 251 } 252 } 253 254 // notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and 255 // SurfaceDataProxies) about the display change event 256 displayChanger.notifyListeners(); 257 } 258 259 /** 260 * Part of the DisplayChangedListener interface: 261 * propagate this event to listeners 262 */ 263 public void paletteChanged() { 264 displayChanger.notifyPaletteChanged(); 265 } 266 267 /** 268 * Returns true when the display is local, false for remote displays. 269 * 270 * @return true when the display is local, false for remote displays 271 */ 272 public abstract boolean isDisplayLocal(); 273 274 /* 275 * ----DISPLAY CHANGE SUPPORT---- 276 */ 277 278 protected SunDisplayChanger displayChanger = new SunDisplayChanger(); 279 280 /** 281 * Add a DisplayChangeListener to be notified when the display settings 282 * are changed. 283 */ 284 public void addDisplayChangedListener(DisplayChangedListener client) { 285 displayChanger.add(client); 286 } 287 288 /** 289 * Remove a DisplayChangeListener from Win32GraphicsEnvironment 290 */ 291 public void removeDisplayChangedListener(DisplayChangedListener client) { 292 displayChanger.remove(client); 293 } 294 295 /* 296 * ----END DISPLAY CHANGE SUPPORT---- 297 */ 298 299 /** 300 * Returns true if FlipBufferStrategy with COPIED buffer contents 301 * is preferred for this peer's GraphicsConfiguration over 302 * BlitBufferStrategy, false otherwise. 303 * 304 * The reason FlipBS could be preferred is that in some configurations 305 * an accelerated copy to the screen is supported (like Direct3D 9) 306 * 307 * @return true if flip strategy should be used, false otherwise 308 */ 309 public boolean isFlipStrategyPreferred(ComponentPeer peer) { 310 return false; 311 } 312 }