/* * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package sun.java2d; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Insets; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.font.TextAttribute; import java.awt.image.BufferedImage; import java.awt.peer.ComponentPeer; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.InputStreamReader; import java.io.IOException; import java.text.AttributedCharacterIterator; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import sun.awt.AppContext; import sun.awt.DisplayChangedListener; import sun.awt.FontConfiguration; import sun.awt.SunDisplayChanger; import sun.font.CompositeFontDescriptor; import sun.font.Font2D; import sun.font.FontManager; import sun.font.NativeFont; /** * This is an implementation of a GraphicsEnvironment object for the * default local GraphicsEnvironment. * * @see GraphicsDevice * @see GraphicsConfiguration */ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment implements FontSupport, DisplayChangedListener { public static boolean isLinux; public static boolean isSolaris; public static boolean isOpenSolaris; public static boolean isWindows; public static boolean noType1Font; private static Font defaultFont; private static String defaultFontFileName; private static String defaultFontName; public static final String lucidaFontName = "Lucida Sans Regular"; public static final String lucidaFileName = "LucidaSansRegular.ttf"; public static boolean debugFonts = false; protected static Logger logger = null; private static ArrayList badFonts; public static String jreLibDirName; public static String jreFontDirName; private static HashSet missingFontFiles = null; private FontConfiguration fontConfig; /* fontPath is the location of all fonts on the system, excluding the * JRE's own font directory but including any path specified using the * sun.java2d.fontpath property. Together with that property, it is * initialised by the getPlatformFontPath() method * This call must be followed by a call to registerFontDirs(fontPath) * once any extra debugging path has been appended. */ protected String fontPath; /* discoveredAllFonts is set to true when all fonts on the font path are * discovered. This usually also implies opening, validating and * registering, but an implementation may be optimized to avold this. * So see also "loadedAllFontFiles" */ private boolean discoveredAllFonts = false; /* loadedAllFontFiles is set to true when all fonts on the font path are * actually opened, validated and registered. This always implies * discoveredAllFonts is true. */ private boolean loadedAllFontFiles = false; protected HashSet registeredFontFiles = new HashSet(); public static String eudcFontFileName; /* Initialised only on windows */ private static boolean isOpenJDK; /** * A few things in Java 2D code are different in OpenJDK, * so need a way to tell which implementation this is. * The absence of Lucida Sans Regular is the simplest way for now. */ public static boolean isOpenJDK() { return isOpenJDK; } static { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { jreLibDirName = System.getProperty("java.home","") + File.separator + "lib"; jreFontDirName = jreLibDirName + File.separator + "fonts"; File lucidaFile = new File(jreFontDirName + File.separator + lucidaFileName); isOpenJDK = !lucidaFile.exists(); String debugLevel = System.getProperty("sun.java2d.debugfonts"); if (debugLevel != null && !debugLevel.equals("false")) { debugFonts = true; logger = Logger.getLogger("sun.java2d"); if (debugLevel.equals("warning")) { logger.setLevel(Level.WARNING); } else if (debugLevel.equals("severe")) { logger.setLevel(Level.SEVERE); } } return null; } }); }; public SunGraphicsEnvironment() { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { String osName = System.getProperty("os.name"); if ("Linux".equals(osName)) { isLinux = true; } else if ("SunOS".equals(osName)) { isSolaris = true; String version = System.getProperty("os.version", "0.0"); try { float ver = Float.parseFloat(version); if (ver > 5.10f) { File f = new File("/etc/release"); FileInputStream fis = new FileInputStream(f); InputStreamReader isr = new InputStreamReader(fis, "ISO-8859-1"); BufferedReader br = new BufferedReader(isr); String line = br.readLine(); if (line.indexOf("OpenSolaris") >= 0) { isOpenSolaris = true; } fis.close(); } } catch (Exception e) { } } else if ("Windows".equals(osName)) { isWindows = true; } noType1Font = "true". equals(System.getProperty("sun.java2d.noType1Font")); if (!isOpenJDK()) { defaultFontName = lucidaFontName; if (useAbsoluteFontFileNames()) { defaultFontFileName = jreFontDirName + File.separator + lucidaFileName; } else { defaultFontFileName = lucidaFileName; } } File badFontFile = new File(jreFontDirName + File.separator + "badfonts.txt"); if (badFontFile.exists()) { FileInputStream fis = null; try { badFonts = new ArrayList(); fis = new FileInputStream(badFontFile); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); while (true) { String name = br.readLine(); if (name == null) { break; } else { if (debugFonts) { logger.warning("read bad font: " + name); } badFonts.add(name); } } } catch (IOException e) { try { if (fis != null) { fis.close(); } } catch (IOException ioe) { } } } /* Here we get the fonts in jre/lib/fonts and register them * so they are always available and preferred over other fonts. * This needs to be registered before the composite fonts as * otherwise some native font that corresponds may be found * as we don't have a way to handle two fonts of the same * name, so the JRE one must be the first one registered. * Pass "true" to registerFonts method as on-screen these * JRE fonts always go through the T2K rasteriser. */ if (isLinux) { /* Linux font configuration uses these fonts */ registerFontDir(jreFontDirName); } registerFontsInDir(jreFontDirName, true, Font2D.JRE_RANK, true, false); /* Register the JRE fonts so that the native platform can * access them. This is used only on Windows so that when * printing the printer driver can access the fonts. */ registerJREFontsWithPlatform(jreFontDirName); /* Create the font configuration and get any font path * that might be specified. */ fontConfig = createFontConfiguration(); if (isOpenJDK()) { String[] fontInfo = FontManager.getDefaultPlatformFont(); defaultFontName = fontInfo[0]; defaultFontFileName = fontInfo[1]; } getPlatformFontPathFromFontConfig(); String extraFontPath = fontConfig.getExtraFontPath(); /* In prior releases the debugging font path replaced * all normally located font directories except for the * JRE fonts dir. This directory is still always located and * placed at the head of the path but as an augmentation * to the previous behaviour the * changes below allow you to additionally append to * the font path by starting with append: or prepend by * starting with a prepend: sign. Eg: to append * -Dsun.java2d.fontpath=append:/usr/local/myfonts * and to prepend * -Dsun.java2d.fontpath=prepend:/usr/local/myfonts Disp * * If there is an appendedfontpath it in the font configuration * it is used instead of searching the system for dirs. * The behaviour of append and prepend is then similar * to the normal case. ie it goes after what * you prepend and * before what you append. If the * sun.java2d.fontpath property is used, but it * neither the append or prepend syntaxes is used then as * except for the JRE dir the path is replaced and it is * up to you to make sure that all the right directories * are located. This is platform and locale-specific so * its almost impossible to get right, so it should be * used with caution. */ boolean prependToPath = false; boolean appendToPath = false; String dbgFontPath = System.getProperty("sun.java2d.fontpath"); if (dbgFontPath != null) { if (dbgFontPath.startsWith("prepend:")) { prependToPath = true; dbgFontPath = dbgFontPath.substring("prepend:".length()); } else if (dbgFontPath.startsWith("append:")) { appendToPath = true; dbgFontPath = dbgFontPath.substring("append:".length()); } } if (debugFonts) { logger.info("JRE font directory: " + jreFontDirName); logger.info("Extra font path: " + extraFontPath); logger.info("Debug font path: " + dbgFontPath); } if (dbgFontPath != null) { /* In debugging mode we register all the paths * Caution: this is a very expensive call on Solaris:- */ fontPath = getPlatformFontPath(noType1Font); if (extraFontPath != null) { fontPath = extraFontPath + File.pathSeparator + fontPath; } if (appendToPath) { fontPath = fontPath + File.pathSeparator + dbgFontPath; } else if (prependToPath) { fontPath = dbgFontPath + File.pathSeparator + fontPath; } else { fontPath = dbgFontPath; } registerFontDirs(fontPath); } else if (extraFontPath != null) { /* If the font configuration contains an "appendedfontpath" * entry, it is interpreted as a set of locations that * should always be registered. * It may be additional to locations normally found for * that place, or it may be locations that need to have * all their paths registered to locate all the needed * platform names. * This is typically when the same .TTF file is referenced * from multiple font.dir files and all of these must be * read to find all the native (XLFD) names for the font, * so that X11 font APIs can be used for as many code * points as possible. */ registerFontDirs(extraFontPath); } /* On Solaris, we need to register the Japanese TrueType * directory so that we can find the corresponding bitmap * fonts. This could be done by listing the directory in * the font configuration file, but we don't want to * confuse users with this quirk. There are no bitmap fonts * for other writing systems that correspond to TrueType * fonts and have matching XLFDs. We need to register the * bitmap fonts only in environments where they're on the * X font path, i.e., in the Japanese locale. * Note that if the X Toolkit is in use the font path isn't * set up by JDK, but users of a JA locale should have it * set up already by their login environment. */ if (isSolaris && Locale.JAPAN.equals(Locale.getDefault())) { registerFontDir("/usr/openwin/lib/locale/ja/X11/fonts/TT"); } initCompositeFonts(fontConfig, null); /* Establish the default font to be used by SG2D etc */ defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); return null; } }); } protected GraphicsDevice[] screens; /** * Returns an array of all of the screen devices. */ public synchronized GraphicsDevice[] getScreenDevices() { GraphicsDevice[] ret = screens; if (ret == null) { int num = getNumScreens(); ret = new GraphicsDevice[num]; for (int i = 0; i < num; i++) { ret[i] = makeScreenDevice(i); } screens = ret; } return ret; } protected abstract int getNumScreens(); protected abstract GraphicsDevice makeScreenDevice(int screennum); /** * Returns the default screen graphics device. */ public GraphicsDevice getDefaultScreenDevice() { return getScreenDevices()[0]; } /** * Returns a Graphics2D object for rendering into the * given BufferedImage. * @throws NullPointerException if BufferedImage argument is null */ public Graphics2D createGraphics(BufferedImage img) { if (img == null) { throw new NullPointerException("BufferedImage cannot be null"); } SurfaceData sd = SurfaceData.getPrimarySurfaceData(img); return new SunGraphics2D(sd, Color.white, Color.black, defaultFont); } /* A call to this method should be followed by a call to * registerFontDirs(..) */ protected String getPlatformFontPath(boolean noType1Font) { if (fontPath == null) { fontPath = FontManager.getFontPath(noType1Font); } return fontPath; } private String[] platformFontDirs; /** * Get all directories which contain installed fonts. */ public String[] getPlatformFontDirs() { if (platformFontDirs == null) { String path = getPlatformFontPath(noType1Font); StringTokenizer parser = new StringTokenizer(path, File.pathSeparator);; ArrayList pathList = new ArrayList(); try { while (parser.hasMoreTokens()) { pathList.add(parser.nextToken()); } } catch (NoSuchElementException e) { } platformFontDirs = pathList.toArray(new String[0]); } return platformFontDirs; } /** * Whether registerFontFile expects absolute or relative * font file names. */ protected boolean useAbsoluteFontFileNames() { return true; } /** * Returns file name for default font, either absolute * or relative as needed by registerFontFile. */ public String getDefaultFontFile() { return defaultFontFileName; } /** * Returns face name for default font, or null if * no face names are used for CompositeFontDescriptors * for this platform. */ public String getDefaultFontFaceName() { return defaultFontName; } public void loadFonts() { if (discoveredAllFonts) { return; } /* Use lock specific to the font system */ synchronized (lucidaFontName) { if (debugFonts) { Thread.dumpStack(); logger.info("SunGraphicsEnvironment.loadFonts() called"); } FontManager.initialiseDeferredFonts(); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { if (fontPath == null) { fontPath = getPlatformFontPath(noType1Font); registerFontDirs(fontPath); } if (fontPath != null) { // this will find all fonts including those already // registered. But we have checks in place to prevent // double registration. if (!FontManager.gotFontsFromPlatform()) { registerFontsOnPath(fontPath, false, Font2D.UNKNOWN_RANK, false, true); loadedAllFontFiles = true; } } FontManager.registerOtherFontFiles(registeredFontFiles); discoveredAllFonts = true; return null; } }); } } public void loadFontFiles() { loadFonts(); if (loadedAllFontFiles) { return; } /* Use lock specific to the font system */ synchronized (lucidaFontName) { if (debugFonts) { Thread.dumpStack(); logger.info("loadAllFontFiles() called"); } java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { if (fontPath == null) { fontPath = getPlatformFontPath(noType1Font); } if (fontPath != null) { // this will find all fonts including those already // registered. But we have checks in place to prevent // double registration. registerFontsOnPath(fontPath, false, Font2D.UNKNOWN_RANK, false, true); } loadedAllFontFiles = true; return null; } }); } } /* * This is for use only within getAllFonts(). * Fonts listed in the fontconfig files for windows were all * on the "deferred" initialisation list. They were registered * either in the course of the application, or in the call to * loadFonts() within getAllFonts(). The fontconfig file specifies * the names of the fonts using the English names. If there's a * different name in the execution locale, then the platform will * report that, and we will construct the font with both names, and * thereby enumerate it twice. This happens for Japanese fonts listed * in the windows fontconfig, when run in the JA locale. The solution * is to rely (in this case) on the platform's font->file mapping to * determine that this name corresponds to a file we already registered. * This works because * - we know when we get here all deferred fonts are already initialised * - when we register a font file, we register all fonts in it. * - we know the fontconfig fonts are all in the windows registry */ private boolean isNameForRegisteredFile(String fontName) { String fileName = FontManager.getFileNameForFontName(fontName); if (fileName == null) { return false; } return registeredFontFiles.contains(fileName); } private Font[] allFonts; /** * Returns all fonts installed in this environment. */ public Font[] getAllInstalledFonts() { if (allFonts == null) { loadFonts(); TreeMap fontMapNames = new TreeMap(); /* warning: the number of composite fonts could change dynamically * if applications are allowed to create them. "allfonts" could * then be stale. */ Font2D[] allfonts = FontManager.getRegisteredFonts(); for (int i=0; i < allfonts.length; i++) { if (!(allfonts[i] instanceof NativeFont)) { fontMapNames.put(allfonts[i].getFontName(null), allfonts[i]); } } String[] platformNames = FontManager.getFontNamesFromPlatform(); if (platformNames != null) { for (int i=0; i 0) { fontNames = new String[fontMapNames.size()]; Object [] keyNames = fontMapNames.keySet().toArray(); for (int i=0; i < keyNames.length; i++) { fontNames[i] = (String)keyNames[i]; } } Font[] fonts = new Font[fontNames.length]; for (int i=0; i < fontNames.length; i++) { fonts[i] = new Font(fontNames[i], Font.PLAIN, 1); Font2D f2d = (Font2D)fontMapNames.get(fontNames[i]); if (f2d != null) { FontManager.setFont2D(fonts[i], f2d.handle); } } allFonts = fonts; } Font []copyFonts = new Font[allFonts.length]; System.arraycopy(allFonts, 0, copyFonts, 0, allFonts.length); return copyFonts; } /** * Returns all fonts available in this environment. */ public Font[] getAllFonts() { Font[] installedFonts = getAllInstalledFonts(); Font[] created = FontManager.getCreatedFonts(); if (created == null || created.length == 0) { return installedFonts; } else { int newlen = installedFonts.length + created.length; Font [] fonts = java.util.Arrays.copyOf(installedFonts, newlen); System.arraycopy(created, 0, fonts, installedFonts.length, created.length); return fonts; } } /** * Default locale can be changed but we need to know the initial locale * as that is what is used by native code. Changing Java default locale * doesn't affect that. * Returns the locale in use when using native code to communicate * with platform APIs. On windows this is known as the "system" locale, * and it is usually the same as the platform locale, but not always, * so this method also checks an implementation property used only * on windows and uses that if set. */ private static Locale systemLocale = null; public static Locale getSystemStartupLocale() { if (systemLocale == null) { systemLocale = (Locale) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { /* On windows the system locale may be different than the * user locale. This is an unsupported configuration, but * in that case we want to return a dummy locale that will * never cause a match in the usage of this API. This is * important because Windows documents that the family * names of fonts are enumerated using the language of * the system locale. BY returning a dummy locale in that * case we do not use the platform API which would not * return us the names we want. */ String fileEncoding = System.getProperty("file.encoding", ""); String sysEncoding = System.getProperty("sun.jnu.encoding"); if (sysEncoding != null && !sysEncoding.equals(fileEncoding)) { return Locale.ROOT; } String language = System.getProperty("user.language", "en"); String country = System.getProperty("user.country",""); String variant = System.getProperty("user.variant",""); return new Locale(language, country, variant); } }); } return systemLocale; } /* Really we need only the JRE fonts family names, but there's little * overhead in doing this the easy way by adding all the currently * known fonts. */ protected void getJREFontFamilyNames(TreeMap familyNames, Locale requestedLocale) { FontManager.registerDeferredJREFonts(jreFontDirName); Font2D[] physicalfonts = FontManager.getPhysicalFonts(); for (int i=0; i < physicalfonts.length; i++) { if (!(physicalfonts[i] instanceof NativeFont)) { String name = physicalfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } private String[] allFamilies; // cache for default locale only private Locale lastDefaultLocale; public String[] getInstalledFontFamilyNames(Locale requestedLocale) { if (requestedLocale == null) { requestedLocale = Locale.getDefault(); } if (allFamilies != null && lastDefaultLocale != null && requestedLocale.equals(lastDefaultLocale)) { String[] copyFamilies = new String[allFamilies.length]; System.arraycopy(allFamilies, 0, copyFamilies, 0, allFamilies.length); return copyFamilies; } TreeMap familyNames = new TreeMap(); // these names are always there and aren't localised String str; str = Font.SERIF; familyNames.put(str.toLowerCase(), str); str = Font.SANS_SERIF; familyNames.put(str.toLowerCase(), str); str = Font.MONOSPACED; familyNames.put(str.toLowerCase(), str); str = Font.DIALOG; familyNames.put(str.toLowerCase(), str); str = Font.DIALOG_INPUT; familyNames.put(str.toLowerCase(), str); /* Platform APIs may be used to get the set of available family * names for the current default locale so long as it is the same * as the start-up system locale, rather than loading all fonts. */ if (requestedLocale.equals(getSystemStartupLocale()) && FontManager.getFamilyNamesFromPlatform(familyNames, requestedLocale)) { /* Augment platform names with JRE font family names */ getJREFontFamilyNames(familyNames, requestedLocale); } else { loadFontFiles(); Font2D[] physicalfonts = FontManager.getPhysicalFonts(); for (int i=0; i < physicalfonts.length; i++) { if (!(physicalfonts[i] instanceof NativeFont)) { String name = physicalfonts[i].getFamilyName(requestedLocale); familyNames.put(name.toLowerCase(requestedLocale), name); } } } String[] retval = new String[familyNames.size()]; Object [] keyNames = familyNames.keySet().toArray(); for (int i=0; i < keyNames.length; i++) { retval[i] = (String)familyNames.get(keyNames[i]); } if (requestedLocale.equals(Locale.getDefault())) { lastDefaultLocale = requestedLocale; allFamilies = new String[retval.length]; System.arraycopy(retval, 0, allFamilies, 0, allFamilies.length); } return retval; } public String[] getAvailableFontFamilyNames(Locale requestedLocale) { String[] installed = getInstalledFontFamilyNames(requestedLocale); /* Use a new TreeMap as used in getInstalledFontFamilyNames * and insert all the keys in lower case, so that the sort order * is the same as the installed families. This preserves historical * behaviour and inserts new families in the right place. * It would have been marginally more efficient to directly obtain * the tree map and just insert new entries, but not so much as * to justify the extra internal interface. */ TreeMap map = FontManager.getCreatedFontFamilyNames(); if (map == null || map.size() == 0) { return installed; } else { for (int i=0; i(); } missingFontFiles.add(fileName); } /** * Creates this environment's FontConfiguration. */ protected abstract FontConfiguration createFontConfiguration(); public abstract FontConfiguration createFontConfiguration(boolean preferLocaleFonts, boolean preferPropFonts); /* * This method asks the font configuration API for all platform names * used as components of composite/logical fonts and iterates over these * looking up their corresponding file name and registers these fonts. * It also ensures that the fonts are accessible via platform APIs. * The composites themselves are then registered. */ private void initCompositeFonts(FontConfiguration fontConfig, ConcurrentHashMap altNameCache) { int numCoreFonts = fontConfig.getNumberCoreFonts(); String[] fcFonts = fontConfig.getPlatformFontNames(); for (int f=0; ffilename * mappings needed to speed start-up on Solaris. * Augment this with the appendedpathname and the mappings * for native (F3) fonts */ //String platName = platformFontName.replaceAll(" ", "_"); //System.out.println("filename."+platName+"="+fontFileName); registerFontFile(fontFileName, nativeNames, Font2D.FONT_CONFIG_RANK, true); } /* This registers accumulated paths from the calls to * addFontToPlatformFontPath(..) and any specified by * the font configuration. Rather than registering * the fonts it puts them in a place and form suitable for * the Toolkit to pick up and use if a toolkit is initialised, * and if it uses X11 fonts. */ registerPlatformFontsUsedByFontConfiguration(); CompositeFontDescriptor[] compositeFontInfo = fontConfig.get2DCompositeFontInfo(); for (int i = 0; i < compositeFontInfo.length; i++) { CompositeFontDescriptor descriptor = compositeFontInfo[i]; String[] componentFileNames = descriptor.getComponentFileNames(); String[] componentFaceNames = descriptor.getComponentFaceNames(); /* It would be better eventually to handle this in the * FontConfiguration code which should also remove duplicate slots */ if (missingFontFiles != null) { for (int ii=0; ii altNameCache, boolean preferLocale, boolean preferProportional) { FontConfiguration fontConfig = createFontConfiguration(preferLocale, preferProportional); initCompositeFonts(fontConfig, altNameCache); } /* If (as we do on X11) need to set a platform font path, * then the needed path may be specified by the platform * specific FontConfiguration class & data file. Such platforms * (ie X11) need to override this method to retrieve this information * into suitable data structures. */ protected void getPlatformFontPathFromFontConfig() { } /** * From the DisplayChangedListener interface; called * when the display mode has been changed. */ public void displayChanged() { // notify screens in device array to do display update stuff for (GraphicsDevice gd : getScreenDevices()) { if (gd instanceof DisplayChangedListener) { ((DisplayChangedListener) gd).displayChanged(); } } // notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and // SurfaceDataProxies) about the display change event displayChanger.notifyListeners(); } /** * Part of the DisplayChangedListener interface: * propagate this event to listeners */ public void paletteChanged() { displayChanger.notifyPaletteChanged(); } /** * Returns true when the display is local, false for remote displays. * * @return true when the display is local, false for remote displays */ public abstract boolean isDisplayLocal(); /* * ----DISPLAY CHANGE SUPPORT---- */ protected SunDisplayChanger displayChanger = new SunDisplayChanger(); /** * Add a DisplayChangeListener to be notified when the display settings * are changed. */ public void addDisplayChangedListener(DisplayChangedListener client) { displayChanger.add(client); } /** * Remove a DisplayChangeListener from Win32GraphicsEnvironment */ public void removeDisplayChangedListener(DisplayChangedListener client) { displayChanger.remove(client); } /* * ----END DISPLAY CHANGE SUPPORT---- */ /** * Returns true if FlipBufferStrategy with COPIED buffer contents * is preferred for this peer's GraphicsConfiguration over * BlitBufferStrategy, false otherwise. * * The reason FlipBS could be preferred is that in some configurations * an accelerated copy to the screen is supported (like Direct3D 9) * * @return true if flip strategy should be used, false otherwise */ public boolean isFlipStrategyPreferred(ComponentPeer peer) { return false; } }