1 /* 2 * Copyright (c) 1997, 2011, 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 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 sun.awt.AppContext; 59 import sun.awt.DisplayChangedListener; 60 import sun.awt.FontConfiguration; 61 import sun.awt.SunDisplayChanger; 62 import sun.font.CompositeFontDescriptor; 63 import sun.font.Font2D; 64 import sun.font.FontManager; 65 import sun.font.FontManagerFactory; 66 import sun.font.FontManagerForSGE; 67 import sun.font.NativeFont; 68 69 /** 70 * This is an implementation of a GraphicsEnvironment object for the 71 * default local GraphicsEnvironment. 72 * 73 * @see GraphicsDevice 74 * @see GraphicsConfiguration 75 */ 76 public abstract class SunGraphicsEnvironment extends GraphicsEnvironment 77 implements DisplayChangedListener { 78 79 public static boolean isOpenSolaris; 80 private static Font defaultFont; 81 82 public SunGraphicsEnvironment() { 83 java.security.AccessController.doPrivileged( 84 new java.security.PrivilegedAction() { 85 public Object run() { 86 String version = System.getProperty("os.version", "0.0"); 87 try { 88 float ver = Float.parseFloat(version); 89 if (ver > 5.10f) { 90 File f = new File("/etc/release"); 91 FileInputStream fis = new FileInputStream(f); 92 InputStreamReader isr 93 = new InputStreamReader(fis, "ISO-8859-1"); 94 BufferedReader br = new BufferedReader(isr); 95 String line = br.readLine(); 96 if (line.indexOf("OpenSolaris") >= 0) { 97 isOpenSolaris = true; 98 } else { 99 /* We are using isOpenSolaris as meaning 100 * we know the Solaris commercial fonts aren't 101 * present. "Solaris Next" (03/10) did not 102 * include these even though its was not 103 * OpenSolaris. Need to revisit how this is 104 * handled but for now as in 6ux, we'll use 105 * the test for a standard font resource as 106 * being an indicator as to whether we need 107 * to treat this as OpenSolaris from a font 108 * config perspective. 109 */ 110 String courierNew = 111 "/usr/openwin/lib/X11/fonts/TrueType/CourierNew.ttf"; 112 File courierFile = new File(courierNew); 113 isOpenSolaris = !courierFile.exists(); 114 } 115 fis.close(); 116 } 117 } catch (Exception e) { 118 } 119 120 /* Establish the default font to be used by SG2D etc */ 121 defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); 122 123 return null; 124 } 125 }); 126 } 127 128 protected GraphicsDevice[] screens; 129 130 /** 131 * Returns an array of all of the screen devices. 132 */ 133 public synchronized GraphicsDevice[] getScreenDevices() { 134 GraphicsDevice[] ret = screens; 135 if (ret == null) { 136 int num = getNumScreens(); 137 ret = new GraphicsDevice[num]; 138 for (int i = 0; i < num; i++) { 139 ret[i] = makeScreenDevice(i); 140 } 141 screens = ret; 142 } 143 return ret; 144 } 145 146 /** 147 * Returns the number of screen devices of this graphics environment. 148 * 149 * @return the number of screen devices of this graphics environment 150 */ 151 protected abstract int getNumScreens(); 152 153 /** 154 * Create and return the screen device with the specified number. The 155 * device with number <code>0</code> will be the default device (returned 156 * by {@link #getDefaultScreenDevice()}. 157 * 158 * @param screennum the number of the screen to create 159 * 160 * @return the created screen device 161 */ 162 protected abstract GraphicsDevice makeScreenDevice(int screennum); 163 164 /** 165 * Returns the default screen graphics device. 166 */ 167 public GraphicsDevice getDefaultScreenDevice() { 168 GraphicsDevice[] screens = getScreenDevices(); 169 return screens.length == 0 ? null : screens[0]; 170 } 171 172 /** 173 * Returns a Graphics2D object for rendering into the 174 * given BufferedImage. 175 * @throws NullPointerException if BufferedImage argument is null 176 */ 177 public Graphics2D createGraphics(BufferedImage img) { 178 if (img == null) { 179 throw new NullPointerException("BufferedImage cannot be null"); 180 } 181 SurfaceData sd = SurfaceData.getPrimarySurfaceData(img); 182 return new SunGraphics2D(sd, Color.white, Color.black, defaultFont); 183 } 184 185 public static FontManagerForSGE getFontManagerForSGE() { 186 FontManager fm = FontManagerFactory.getInstance(); 187 return (FontManagerForSGE) fm; 188 } 189 190 /* Modifies the behaviour of a subsequent call to preferLocaleFonts() 191 * to use Mincho instead of Gothic for dialoginput in JA locales 192 * on windows. Not needed on other platforms. 193 * 194 * DO NOT MOVE OR RENAME OR OTHERWISE ALTER THIS METHOD. 195 * ITS USED BY SOME NON-JRE INTERNAL CODE. 196 */ 197 public static void useAlternateFontforJALocales() { 198 getFontManagerForSGE().useAlternateFontforJALocales(); 199 } 200 201 /** 202 * Returns all fonts available in this environment. 203 */ 204 public Font[] getAllFonts() { 205 FontManagerForSGE fm = getFontManagerForSGE(); 206 Font[] installedFonts = fm.getAllInstalledFonts(); 207 Font[] created = fm.getCreatedFonts(); 208 if (created == null || created.length == 0) { 209 return installedFonts; 210 } else { 211 int newlen = installedFonts.length + created.length; 212 Font [] fonts = java.util.Arrays.copyOf(installedFonts, newlen); 213 System.arraycopy(created, 0, fonts, 214 installedFonts.length, created.length); 215 return fonts; 216 } 217 } 218 219 public String[] getAvailableFontFamilyNames(Locale requestedLocale) { 220 FontManagerForSGE fm = getFontManagerForSGE(); 221 String[] installed = fm.getInstalledFontFamilyNames(requestedLocale); 222 /* Use a new TreeMap as used in getInstalledFontFamilyNames 223 * and insert all the keys in lower case, so that the sort order 224 * is the same as the installed families. This preserves historical 225 * behaviour and inserts new families in the right place. 226 * It would have been marginally more efficient to directly obtain 227 * the tree map and just insert new entries, but not so much as 228 * to justify the extra internal interface. 229 */ 230 TreeMap<String, String> map = fm.getCreatedFontFamilyNames(); 231 if (map == null || map.size() == 0) { 232 return installed; 233 } else { 234 for (int i=0; i<installed.length; i++) { 235 map.put(installed[i].toLowerCase(requestedLocale), 236 installed[i]); 237 } 238 String[] retval = new String[map.size()]; 239 Object [] keyNames = map.keySet().toArray(); 240 for (int i=0; i < keyNames.length; i++) { 241 retval[i] = (String)map.get(keyNames[i]); 242 } 243 return retval; 244 } 245 } 246 247 public String[] getAvailableFontFamilyNames() { 248 return getAvailableFontFamilyNames(Locale.getDefault()); 249 } 250 251 /** 252 * Return the bounds of a GraphicsDevice, less its screen insets. 253 * See also java.awt.GraphicsEnvironment.getUsableBounds(); 254 */ 255 public static Rectangle getUsableBounds(GraphicsDevice gd) { 256 GraphicsConfiguration gc = gd.getDefaultConfiguration(); 257 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); 258 Rectangle usableBounds = gc.getBounds(); 259 260 usableBounds.x += insets.left; 261 usableBounds.y += insets.top; 262 usableBounds.width -= (insets.left + insets.right); 263 usableBounds.height -= (insets.top + insets.bottom); 264 265 return usableBounds; 266 } 267 268 /** 269 * From the DisplayChangedListener interface; called 270 * when the display mode has been changed. 271 */ 272 public void displayChanged() { 273 // notify screens in device array to do display update stuff 274 for (GraphicsDevice gd : getScreenDevices()) { 275 if (gd instanceof DisplayChangedListener) { 276 ((DisplayChangedListener) gd).displayChanged(); 277 } 278 } 279 280 // notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and 281 // SurfaceDataProxies) about the display change event 282 displayChanger.notifyListeners(); 283 } 284 285 /** 286 * Part of the DisplayChangedListener interface: 287 * propagate this event to listeners 288 */ 289 public void paletteChanged() { 290 displayChanger.notifyPaletteChanged(); 291 } 292 293 /** 294 * Returns true when the display is local, false for remote displays. 295 * 296 * @return true when the display is local, false for remote displays 297 */ 298 public abstract boolean isDisplayLocal(); 299 300 /* 301 * ----DISPLAY CHANGE SUPPORT---- 302 */ 303 304 protected SunDisplayChanger displayChanger = new SunDisplayChanger(); 305 306 /** 307 * Add a DisplayChangeListener to be notified when the display settings 308 * are changed. 309 */ 310 public void addDisplayChangedListener(DisplayChangedListener client) { 311 displayChanger.add(client); 312 } 313 314 /** 315 * Remove a DisplayChangeListener from Win32GraphicsEnvironment 316 */ 317 public void removeDisplayChangedListener(DisplayChangedListener client) { 318 displayChanger.remove(client); 319 } 320 321 /* 322 * ----END DISPLAY CHANGE SUPPORT---- 323 */ 324 325 /** 326 * Returns true if FlipBufferStrategy with COPIED buffer contents 327 * is preferred for this peer's GraphicsConfiguration over 328 * BlitBufferStrategy, false otherwise. 329 * 330 * The reason FlipBS could be preferred is that in some configurations 331 * an accelerated copy to the screen is supported (like Direct3D 9) 332 * 333 * @return true if flip strategy should be used, false otherwise 334 */ 335 public boolean isFlipStrategyPreferred(ComponentPeer peer) { 336 return false; 337 } 338 }