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