001: /*
002: * Copyright 1997-2006 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 sun.awt;
027:
028: import java.awt.GraphicsDevice;
029: import java.awt.GraphicsEnvironment;
030: import java.awt.Toolkit;
031: import java.io.File;
032: import java.io.IOException;
033: import java.lang.ref.WeakReference;
034: import java.util.ArrayList;
035: import java.util.ListIterator;
036: import java.util.NoSuchElementException;
037: import java.util.StringTokenizer;
038: import sun.awt.DisplayChangedListener;
039: import sun.awt.SunDisplayChanger;
040: import sun.awt.windows.WFontConfiguration;
041: import sun.awt.windows.WPrinterJob;
042: import sun.awt.windows.WToolkit;
043: import sun.font.FontManager;
044: import sun.java2d.SunGraphicsEnvironment;
045: import sun.java2d.windows.WindowsFlags;
046:
047: /**
048: * This is an implementation of a GraphicsEnvironment object for the
049: * default local GraphicsEnvironment used by the Java Runtime Environment
050: * for Windows.
051: *
052: * @see GraphicsDevice
053: * @see GraphicsConfiguration
054: * @version 1.46 06/15/07
055: */
056:
057: public class Win32GraphicsEnvironment extends SunGraphicsEnvironment {
058: static {
059: // Ensure awt is loaded already. Also, this forces static init
060: // of WToolkit and Toolkit, which we depend upon
061: WToolkit.loadLibraries();
062: // setup flags before initializing native layer
063: WindowsFlags.initFlags();
064: initDisplayWrapper();
065: eudcFontFileName = getEUDCFontFile();
066: }
067:
068: /**
069: * Noop function that just acts as an entry point for someone to force
070: * a static initialization of this class.
071: */
072: public static void init() {
073: }
074:
075: /**
076: * Initializes native components of the graphics environment. This
077: * includes everything from the native GraphicsDevice elements to
078: * the DirectX rendering layer.
079: */
080: private static native void initDisplay();
081:
082: private static boolean displayInitialized; // = false;
083:
084: public static void initDisplayWrapper() {
085: if (!displayInitialized) {
086: displayInitialized = true;
087: initDisplay();
088: }
089: }
090:
091: public Win32GraphicsEnvironment() {
092: }
093:
094: protected native int getNumScreens();
095:
096: protected native int getDefaultScreen();
097:
098: public GraphicsDevice getDefaultScreenDevice() {
099: return getScreenDevices()[getDefaultScreen()];
100: }
101:
102: /**
103: * Returns the number of pixels per logical inch along the screen width.
104: * In a system with multiple display monitors, this value is the same for
105: * all monitors.
106: * @returns number of pixels per logical inch in X direction
107: */
108: public native int getXResolution();
109:
110: /**
111: * Returns the number of pixels per logical inch along the screen height.
112: * In a system with multiple display monitors, this value is the same for
113: * all monitors.
114: * @returns number of pixels per logical inch in Y direction
115: */
116: public native int getYResolution();
117:
118: /*
119: * ----DISPLAY CHANGE SUPPORT----
120: */
121:
122: // list of invalidated graphics devices (those which were removed)
123: private ArrayList<WeakReference<Win32GraphicsDevice>> oldDevices;
124:
125: /*
126: * From DisplayChangeListener interface.
127: * Called from WToolkit and executed on the event thread when the
128: * display settings are changed.
129: */
130: @Override
131: public void displayChanged() {
132: // getNumScreens() will return the correct current number of screens
133: GraphicsDevice newDevices[] = new GraphicsDevice[getNumScreens()];
134: GraphicsDevice oldScreens[] = screens;
135: // go through the list of current devices and determine if they
136: // could be reused, or will have to be replaced
137: if (oldScreens != null) {
138: for (int i = 0; i < oldScreens.length; i++) {
139: if (!(screens[i] instanceof Win32GraphicsDevice)) {
140: // REMIND: can we ever have anything other than Win32GD?
141: assert (false) : oldScreens[i];
142: continue;
143: }
144: Win32GraphicsDevice gd = (Win32GraphicsDevice) oldScreens[i];
145: // devices may be invalidated from the native code when the
146: // display change happens (device add/removal also causes a
147: // display change)
148: if (!gd.isValid()) {
149: if (oldDevices == null) {
150: oldDevices = new ArrayList<WeakReference<Win32GraphicsDevice>>();
151: }
152: oldDevices
153: .add(new WeakReference<Win32GraphicsDevice>(
154: gd));
155: } else if (i < newDevices.length) {
156: // reuse the device
157: newDevices[i] = gd;
158: }
159: }
160: oldScreens = null;
161: }
162: // create the new devices (those that weren't reused)
163: for (int i = 0; i < newDevices.length; i++) {
164: if (newDevices[i] == null) {
165: newDevices[i] = makeScreenDevice(i);
166: }
167: }
168: // install the new array of devices
169: // Note: no synchronization here, it doesn't matter if a thread gets
170: // a new or an old array this time around
171: screens = newDevices;
172: for (GraphicsDevice gd : screens) {
173: if (gd instanceof DisplayChangedListener) {
174: ((DisplayChangedListener) gd).displayChanged();
175: }
176: }
177: // re-invalidate all old devices. It's needed because those in the list
178: // may become "invalid" again - if the current default device is removed,
179: // for example. Also, they need to be notified about display
180: // changes as well.
181: if (oldDevices != null) {
182: int defScreen = getDefaultScreen();
183: for (ListIterator<WeakReference<Win32GraphicsDevice>> it = oldDevices
184: .listIterator(); it.hasNext();) {
185: Win32GraphicsDevice gd = it.next().get();
186: if (gd != null) {
187: gd.invalidate(defScreen);
188: gd.displayChanged();
189: } else {
190: // no more references to this device, remove it
191: it.remove();
192: }
193: }
194: }
195: // Reset the static GC for the (possibly new) default screen
196: WToolkit.resetGC();
197:
198: // notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and
199: // CachingSurfaceManagers) about the display change event
200: displayChanger.notifyListeners();
201: // note: do not call super.displayChanged, we've already done everything
202: }
203:
204: /*
205: * ----END DISPLAY CHANGE SUPPORT----
206: */
207:
208: /* Used on Windows to obtain from the windows registry the name
209: * of a file containing the system EUFC font. If running in one of
210: * the locales for which this applies, and one is defined, the font
211: * defined by this file is appended to all composite fonts as a
212: * fallback component.
213: */
214: private static native String getEUDCFontFile();
215:
216: /**
217: * Whether registerFontFile expects absolute or relative
218: * font file names.
219: */
220: protected boolean useAbsoluteFontFileNames() {
221: return false;
222: }
223:
224: /* Unlike the shared code version, this expects a base file name -
225: * not a full path name.
226: * The font configuration file has base file names and the FontConfiguration
227: * class reports these back to the GraphicsEnvironment, so these
228: * are the componentFileNames of CompositeFonts.
229: */
230: protected void registerFontFile(String fontFileName,
231: String[] nativeNames, int fontRank, boolean defer) {
232:
233: // REMIND: case compare depends on platform
234: if (registeredFontFiles.contains(fontFileName)) {
235: return;
236: }
237: registeredFontFiles.add(fontFileName);
238:
239: int fontFormat;
240: if (ttFilter.accept(null, fontFileName)) {
241: fontFormat = FontManager.FONTFORMAT_TRUETYPE;
242: } else if (t1Filter.accept(null, fontFileName)) {
243: fontFormat = FontManager.FONTFORMAT_TYPE1;
244: } else {
245: /* on windows we don't use/register native fonts */
246: return;
247: }
248:
249: if (fontPath == null) {
250: fontPath = getPlatformFontPath(noType1Font);
251: }
252:
253: /* Look in the JRE font directory first.
254: * This is playing it safe as we would want to find fonts in the
255: * JRE font directory ahead of those in the system directory
256: */
257: String tmpFontPath = jreFontDirName + File.pathSeparator
258: + fontPath;
259: StringTokenizer parser = new StringTokenizer(tmpFontPath,
260: File.pathSeparator);
261:
262: boolean found = false;
263: try {
264: while (!found && parser.hasMoreTokens()) {
265: String newPath = parser.nextToken();
266: File theFile = new File(newPath, fontFileName);
267: if (theFile.canRead()) {
268: found = true;
269: String path = theFile.getAbsolutePath();
270: if (defer) {
271: FontManager.registerDeferredFont(fontFileName,
272: path, nativeNames, fontFormat, true,
273: fontRank);
274: } else {
275: FontManager.registerFontFile(path, nativeNames,
276: fontFormat, true, fontRank);
277: }
278: break;
279: }
280: }
281: } catch (NoSuchElementException e) {
282: System.err.println(e);
283: }
284: if (!found) {
285: addToMissingFontFileList(fontFileName);
286: }
287: }
288:
289: /* register only TrueType/OpenType fonts
290: * Because these need to be registed just for use when printing,
291: * we defer the actual registration and the static initialiser
292: * for the printing class makes the call to registerJREFontsForPrinting()
293: */
294: static String fontsForPrinting = null;
295:
296: protected void registerJREFontsWithPlatform(String pathName) {
297: fontsForPrinting = pathName;
298: }
299:
300: public static void registerJREFontsForPrinting() {
301: String pathName = null;
302: synchronized (Win32GraphicsEnvironment.class) {
303: GraphicsEnvironment.getLocalGraphicsEnvironment();
304: if (fontsForPrinting == null) {
305: return;
306: }
307: pathName = fontsForPrinting;
308: fontsForPrinting = null;
309: }
310: File f1 = new File(pathName);
311: String[] ls = f1.list(new TTFilter());
312: if (ls == null) {
313: return;
314: }
315: for (int i = 0; i < ls.length; i++) {
316: File fontFile = new File(f1, ls[i]);
317: registerFontWithPlatform(fontFile.getAbsolutePath());
318: }
319: }
320:
321: protected static native void registerFontWithPlatform(
322: String fontName);
323:
324: protected static native void deRegisterFontWithPlatform(
325: String fontName);
326:
327: protected GraphicsDevice makeScreenDevice(int screennum) {
328: return new Win32GraphicsDevice(screennum);
329: }
330:
331: // Implements SunGraphicsEnvironment.createFontConfiguration.
332: protected FontConfiguration createFontConfiguration() {
333: return new WFontConfiguration(this );
334: }
335:
336: public FontConfiguration createFontConfiguration(
337: boolean preferLocaleFonts, boolean preferPropFonts) {
338:
339: return new WFontConfiguration(this, preferLocaleFonts,
340: preferPropFonts);
341: }
342: }
|