51 import sun.java2d.SunGraphicsEnvironment;
52 import sun.java2d.SurfaceManagerFactory;
53 import sun.java2d.UnixSurfaceManagerFactory;
54
55 /**
56 * This is an implementation of a GraphicsEnvironment object for the
57 * default local GraphicsEnvironment used by the Java Runtime Environment
58 * for X11 environments.
59 *
60 * @see GraphicsDevice
61 * @see GraphicsConfiguration
62 */
63 public class X11GraphicsEnvironment
64 extends SunGraphicsEnvironment
65 {
66 private static final Logger log = Logger.getLogger("sun.awt.X11GraphicsEnvironment");
67 private static final Logger screenLog = Logger.getLogger("sun.awt.screen.X11GraphicsEnvironment");
68
69 private static Boolean xinerState;
70
71 /*
72 * This is the set of font directories needed to be on the X font path
73 * to enable AWT heavyweights to find all of the font configuration fonts.
74 * It is populated by :
75 * - awtfontpath entries in the fontconfig.properties
76 * - parent directories of "core" fonts used in the fontconfig.properties
77 * - looking up font dirs in the xFontDirsMap where the key is a fontID
78 * (cut down version of the XLFD read from the font configuration file).
79 * This set is nulled out after use to free heap space.
80 */
81 private static HashSet<String> fontConfigDirs = null;
82
83 /*
84 * fontNameMap is a map from a fontID (which is a substring of an XLFD like
85 * "-monotype-arial-bold-r-normal-iso8859-7")
86 * to font file path like
87 * /usr/openwin/lib/locale/iso_8859_7/X11/fonts/TrueType/ArialBoldItalic.ttf
88 * It's used in a couple of methods like
89 * getFileNameFomPlatformName(..) to help locate the font file.
90 * We use this substring of a full XLFD because the font configuration files
91 * define the XLFDs in a way that's easier to make into a request.
92 * E.g., the -0-0-0-0-p-0- reported by X is -*-%d-*-*-p-*- in the font
93 * configuration files. We need to remove that part for comparisons.
94 */
95 private static Map fontNameMap = new HashMap();
96
97 /* xFontDirsMap is also a map from a font ID to a font filepath.
98 * The difference from fontNameMap is just that it does not have
99 * resolved symbolic links. Normally this is not interesting except
100 * that we need to know the directory in which a font was found to
101 * add it to the X font server path, since although the files may
102 * be linked, the fonts.dir is different and specific to the encoding
103 * handled by that directory. This map is nulled out after use to free
104 * heap space. If the optimal path is taken, such that all fonts in
105 * font configuration files are referenced by filename, then the font
106 * dir can be directly derived as its parent directory.
107 * If a font is used by two XLFDs, each corresponding to a different
108 * X11 font directory, then precautions must be taken to include both
109 * directories.
110 */
111 private static Map xFontDirsMap;
112
113 /*
114 * xlfdMap is a map from a platform path like
115 * /usr/openwin/lib/locale/ja/X11/fonts/TT/HG-GothicB.ttf to an XLFD like
116 * "-ricoh-hg gothic b-medium-r-normal--0-0-0-0-m-0-jisx0201.1976-0"
117 * Because there may be multiple native names, because the font is used
118 * to support multiple X encodings for example, the value of an entry in
119 * this map is always a vector where we store all the native names.
120 * For fonts which we don't understand the key isn't a pathname, its
121 * the full XLFD string like :-
122 * "-ricoh-hg gothic b-medium-r-normal--0-0-0-0-m-0-jisx0201.1976-0"
123 */
124 private static Map xlfdMap = new HashMap();
125
126 /*
127 * Used to eliminate redundant work. When a font directory is
128 * registered it added to this list. Subsequent registrations for the
129 * same directory can then be skipped by checking this Map.
130 * Access to this map is not synchronised here since creation
131 * of the singleton GE instance is already synchronised and that is
132 * the only code path that accesses this map.
133 */
134 private static HashMap registeredDirs = new HashMap();
135
136 /* Array of directories to be added to the X11 font path.
137 * Used by static method called from Toolkits which use X11 fonts.
138 * Specifically this means MToolkit
139 */
140 private static String[] fontdirs = null;
141
142 static {
143 java.security.AccessController.doPrivileged(
144 new java.security.PrivilegedAction() {
145 public Object run() {
146 System.loadLibrary("awt");
147
148 /*
149 * Note: The MToolkit object depends on the static initializer
150 * of X11GraphicsEnvironment to initialize the connection to
151 * the X11 server.
152 */
153 if (!isHeadless()) {
154 // first check the OGL system property
155 boolean glxRequested = false;
156 String prop = System.getProperty("sun.java2d.opengl");
157 if (prop != null) {
158 if (prop.equals("true") || prop.equals("t")) {
159 glxRequested = true;
160 } else if (prop.equals("True") || prop.equals("T")) {
161 glxRequested = true;
217 */
218 private static native void initDisplay(boolean glxRequested);
219
220 public X11GraphicsEnvironment() {
221 }
222
223 protected native int getNumScreens();
224
225 protected GraphicsDevice makeScreenDevice(int screennum) {
226 return new X11GraphicsDevice(screennum);
227 }
228
229 protected native int getDefaultScreenNum();
230 /**
231 * Returns the default screen graphics device.
232 */
233 public GraphicsDevice getDefaultScreenDevice() {
234 return getScreenDevices()[getDefaultScreenNum()];
235 }
236
237 @Override
238 public boolean isDisplayLocal() {
239 if (isDisplayLocal == null) {
240 SunToolkit.awtLock();
241 try {
242 if (isDisplayLocal == null) {
243 isDisplayLocal = Boolean.valueOf(_isDisplayLocal());
244 }
245 } finally {
246 SunToolkit.awtUnlock();
247 }
248 }
249 return isDisplayLocal.booleanValue();
250 }
251
252 private static boolean _isDisplayLocal() {
253 if (isHeadless()) {
254 return true;
255 }
256
257 String isRemote = (String)java.security.AccessController.doPrivileged(
294 } catch (SocketException e1) {
295 System.err.println(e1.getMessage());
296 return Boolean.FALSE;
297 }
298
299 for (; interfaces.hasMoreElements();) {
300 locals = ((NetworkInterface)interfaces.nextElement()).getInetAddresses();
301 for (; locals.hasMoreElements();) {
302 for (int i = 0; i < remAddr.length; i++) {
303 if (locals.nextElement().equals(remAddr[i])) {
304 return Boolean.TRUE;
305 }
306 }
307 }
308 }
309 return Boolean.FALSE;
310 }});
311 return result.booleanValue();
312 }
313
314 /* These maps are used on Linux where we reference the Lucida oblique
315 * fonts in fontconfig files even though they aren't in the standard
316 * font directory. This explicitly remaps the XLFDs for these to the
317 * correct base font. This is needed to prevent composite fonts from
318 * defaulting to the Lucida Sans which is a bad substitute for the
319 * monospaced Lucida Sans Typewriter. Also these maps prevent the
320 * JRE from doing wasted work at start up.
321 */
322 HashMap<String, String> oblmap = null;
323
324 private String getObliqueLucidaFontID(String fontID) {
325 if (fontID.startsWith("-lucidasans-medium-i-normal") ||
326 fontID.startsWith("-lucidasans-bold-i-normal") ||
327 fontID.startsWith("-lucidatypewriter-medium-i-normal") ||
328 fontID.startsWith("-lucidatypewriter-bold-i-normal")) {
329 return fontID.substring(0, fontID.indexOf("-i-"));
330 } else {
331 return null;
332 }
333 }
334
335 private void initObliqueLucidaFontMap() {
336 oblmap = new HashMap<String, String>();
337 oblmap.put("-lucidasans-medium",
338 jreLibDirName+"/fonts/LucidaSansRegular.ttf");
339 oblmap.put("-lucidasans-bold",
340 jreLibDirName+"/fonts/LucidaSansDemiBold.ttf");
341 oblmap.put("-lucidatypewriter-medium",
342 jreLibDirName+"/fonts/LucidaTypewriterRegular.ttf");
343 oblmap.put("-lucidatypewriter-bold",
344 jreLibDirName+"/fonts/LucidaTypewriterBold.ttf");
345 }
346
347 /**
348 * Takes family name property in the following format:
349 * "-linotype-helvetica-medium-r-normal-sans-*-%d-*-*-p-*-iso8859-1"
350 * and returns the name of the corresponding physical font.
351 * This code is used to resolve font configuration fonts, and expects
352 * only to get called for these fonts.
353 */
354 public String getFileNameFromPlatformName(String platName) {
355
356 /* If the FontConfig file doesn't use xlfds, or its
357 * FcFontConfiguration, this may be already a file name.
358 */
359 if (platName.startsWith("/")) {
360 return platName;
361 }
362
363 String fileName = null;
364 String fontID = specificFontIDForName(platName);
365
366 /* If the font filename has been explicitly assigned in the
367 * font configuration file, use it. This avoids accessing
368 * the wrong fonts on Linux, where different fonts (some
369 * of which may not be usable by 2D) may share the same
370 * specific font ID. It may also speed up the lookup.
371 */
372 fileName = super.getFileNameFromPlatformName(platName);
373 if (fileName != null) {
374 if (isHeadless() && fileName.startsWith("-")) {
375 /* if it's headless, no xlfd should be used */
376 return null;
377 }
378 if (fileName.startsWith("/")) {
379 /* If a path is assigned in the font configuration file,
380 * it is required that the config file also specify using the
381 * new awtfontpath key the X11 font directories
382 * which must be added to the X11 font path to support
383 * AWT access to that font. For that reason we no longer
384 * have code here to add the parent directory to the list
385 * of font config dirs, since the parent directory may not
386 * be sufficient if fonts are symbolically linked to a
387 * different directory.
388 *
389 * Add this XLFD (platform name) to the list of known
390 * ones for this file.
391 */
392 Vector xVal = (Vector) xlfdMap.get(fileName);
393 if (xVal == null) {
394 /* Try to be robust on Linux distros which move fonts
395 * around by verifying that the fileName represents a
396 * file that exists. If it doesn't, set it to null
397 * to trigger a search.
398 */
399 if (getFontConfiguration().needToSearchForFile(fileName)) {
400 fileName = null;
401 }
402 if (fileName != null) {
403 xVal = new Vector();
404 xVal.add(platName);
405 xlfdMap.put(fileName, xVal);
406 }
407 } else {
408 if (!xVal.contains(platName)) {
409 xVal.add(platName);
410 }
411 }
412 }
413 if (fileName != null) {
414 fontNameMap.put(fontID, fileName);
415 return fileName;
416 }
417 }
418
419 if (fontID != null) {
420 fileName = (String)fontNameMap.get(fontID);
421 /* On Linux check for the Lucida Oblique fonts */
422 if (fileName == null && isLinux && !isOpenJDK()) {
423 if (oblmap == null) {
424 initObliqueLucidaFontMap();
425 }
426 String oblkey = getObliqueLucidaFontID(fontID);
427 if (oblkey != null) {
428 fileName = oblmap.get(oblkey);
429 }
430 }
431 if (fontPath == null &&
432 (fileName == null || !fileName.startsWith("/"))) {
433 if (debugFonts) {
434 logger.warning("** Registering all font paths because " +
435 "can't find file for " + platName);
436 }
437 fontPath = getPlatformFontPath(noType1Font);
438 registerFontDirs(fontPath);
439 if (debugFonts) {
440 logger.warning("** Finished registering all font paths");
441 }
442 fileName = (String)fontNameMap.get(fontID);
443 }
444 if (fileName == null && !isHeadless()) {
445 /* Query X11 directly to see if this font is available
446 * as a native font.
447 */
448 fileName = getX11FontName(platName);
449 }
450 if (fileName == null) {
451 fontID = switchFontIDForName(platName);
452 fileName = (String)fontNameMap.get(fontID);
453 }
454 if (fileName != null) {
455 fontNameMap.put(fontID, fileName);
456 }
457 }
458 return fileName;
459 }
460
461 private static String getX11FontName(String platName) {
462 String xlfd = platName.replaceAll("%d", "*");
463 if (NativeFont.fontExists(xlfd)) {
464 return xlfd;
465 } else {
466 return null;
467 }
468 }
469
470 /**
471 * Returns the face name for the given XLFD.
472 */
473 public String getFileNameFromXLFD(String name) {
474 String fileName = null;
475 String fontID = specificFontIDForName(name);
476 if (fontID != null) {
477 fileName = (String)fontNameMap.get(fontID);
478 if (fileName == null) {
479 fontID = switchFontIDForName(name);
480 fileName = (String)fontNameMap.get(fontID);
481 }
482 if (fileName == null) {
483 fileName = getDefaultFontFile();
484 }
485 }
486 return fileName;
487 }
488
489 // constants identifying XLFD and font ID fields
490 private static final int FOUNDRY_FIELD = 1;
491 private static final int FAMILY_NAME_FIELD = 2;
492 private static final int WEIGHT_NAME_FIELD = 3;
493 private static final int SLANT_FIELD = 4;
494 private static final int SETWIDTH_NAME_FIELD = 5;
495 private static final int ADD_STYLE_NAME_FIELD = 6;
496 private static final int PIXEL_SIZE_FIELD = 7;
497 private static final int POINT_SIZE_FIELD = 8;
498 private static final int RESOLUTION_X_FIELD = 9;
499 private static final int RESOLUTION_Y_FIELD = 10;
500 private static final int SPACING_FIELD = 11;
501 private static final int AVERAGE_WIDTH_FIELD = 12;
502 private static final int CHARSET_REGISTRY_FIELD = 13;
503 private static final int CHARSET_ENCODING_FIELD = 14;
504
505 private String switchFontIDForName(String name) {
506
507 int[] hPos = new int[14];
508 int hyphenCnt = 1;
509 int pos = 1;
510
511 while (pos != -1 && hyphenCnt < 14) {
512 pos = name.indexOf('-', pos);
513 if (pos != -1) {
514 hPos[hyphenCnt++] = pos;
515 pos++;
516 }
517 }
518
519 if (hyphenCnt != 14) {
520 if (debugFonts) {
521 logger.severe("Font Configuration Font ID is malformed:" + name);
522 }
523 return name; // what else can we do?
524 }
525
526 String slant = name.substring(hPos[SLANT_FIELD-1]+1,
527 hPos[SLANT_FIELD]);
528 String family = name.substring(hPos[FAMILY_NAME_FIELD-1]+1,
529 hPos[FAMILY_NAME_FIELD]);
530 String registry = name.substring(hPos[CHARSET_REGISTRY_FIELD-1]+1,
531 hPos[CHARSET_REGISTRY_FIELD]);
532 String encoding = name.substring(hPos[CHARSET_ENCODING_FIELD-1]+1);
533
534 if (slant.equals("i")) {
535 slant = "o";
536 } else if (slant.equals("o")) {
537 slant = "i";
538 }
539 // workaround for #4471000
540 if (family.equals("itc zapfdingbats")
541 && registry.equals("sun")
542 && encoding.equals("fontspecific")){
543 registry = "adobe";
544 }
545 StringBuffer sb =
546 new StringBuffer(name.substring(hPos[FAMILY_NAME_FIELD-1],
547 hPos[SLANT_FIELD-1]+1));
548 sb.append(slant);
549 sb.append(name.substring(hPos[SLANT_FIELD],
550 hPos[SETWIDTH_NAME_FIELD]+1));
551 sb.append(registry);
552 sb.append(name.substring(hPos[CHARSET_ENCODING_FIELD-1]));
553 String retval = sb.toString().toLowerCase (Locale.ENGLISH);
554 return retval;
555 }
556
557
558 private String specificFontIDForName(String name) {
559
560 int[] hPos = new int[14];
561 int hyphenCnt = 1;
562 int pos = 1;
563
564 while (pos != -1 && hyphenCnt < 14) {
565 pos = name.indexOf('-', pos);
566 if (pos != -1) {
567 hPos[hyphenCnt++] = pos;
568 pos++;
569 }
570 }
571
572 if (hyphenCnt != 14) {
573 if (debugFonts) {
574 logger.severe("Font Configuration Font ID is malformed:" + name);
575 }
576 return name; // what else can we do?
577 }
578
579 StringBuffer sb =
580 new StringBuffer(name.substring(hPos[FAMILY_NAME_FIELD-1],
581 hPos[SETWIDTH_NAME_FIELD]));
582 sb.append(name.substring(hPos[CHARSET_REGISTRY_FIELD-1]));
583 String retval = sb.toString().toLowerCase (Locale.ENGLISH);
584 return retval;
585 }
586
587 protected String[] getNativeNames(String fontFileName,
588 String platformName) {
589 Vector nativeNames;
590 if ((nativeNames=(Vector)xlfdMap.get(fontFileName))==null) {
591 if (platformName == null) {
592 return null;
593 } else {
594 /* back-stop so that at least the name used in the
595 * font configuration file is known as a native name
596 */
597 String []natNames = new String[1];
598 natNames[0] = platformName;
599 return natNames;
600 }
601 } else {
602 int len = nativeNames.size();
603 return (String[])nativeNames.toArray(new String[len]);
604 }
605 }
606
607
608 // An X font spec (xlfd) includes an encoding. The same TrueType font file
609 // may be referenced from different X font directories in font.dir files
610 // to support use in multiple encodings by X apps.
611 // So for the purposes of font configuration logical fonts where AWT
612 // heavyweights need to access the font via X APIs we need to ensure that
613 // the directory for precisely the encodings needed by this are added to
614 // the x font path. This requires that we note the platform names
615 // specified in font configuration files and use that to identify the
616 // X font directory that contains a font.dir file for that platform name
617 // and add it to the X font path (if display is local)
618 // Here we make use of an already built map of xlfds to font locations
619 // to add the font location to the set of those required to build the
620 // x font path needed by AWT.
621 // These are added to the x font path later.
622 // All this is necessary because on Solaris the font.dir directories
623 // may contain not real font files, but symbolic links to the actual
624 // location but that location is not suitable for the x font path, since
625 // it probably doesn't have a font.dir at all and certainly not one
626 // with the required encodings
627 // If the fontconfiguration file is properly set up so that all fonts
628 // are mapped to files then we will never trigger initialising
629 // xFontDirsMap (it will be null). In this case the awtfontpath entries
630 // must specify all the X11 directories needed by AWT.
631 protected void addFontToPlatformFontPath(String platformName) {
632 if (xFontDirsMap != null) {
633 String fontID = specificFontIDForName(platformName);
634 String dirName = (String)xFontDirsMap.get(fontID);
635 if (dirName != null) {
636 fontConfigDirs.add(dirName);
637 }
638 }
639 return;
640 }
641
642 protected void getPlatformFontPathFromFontConfig() {
643 if (fontConfigDirs == null) {
644 fontConfigDirs = getFontConfiguration().getAWTFontPathSet();
645 if (debugFonts && fontConfigDirs != null) {
646 String[] names = fontConfigDirs.toArray(new String[0]);
647 for (int i=0;i<names.length;i++) {
648 logger.info("awtfontpath : " + names[i]);
649 }
650 }
651 }
652 }
653
654 protected void registerPlatformFontsUsedByFontConfiguration() {
655 if (fontConfigDirs == null) {
656 return;
657 }
658 if (isLinux) {
659 fontConfigDirs.add(jreLibDirName+File.separator+"oblique-fonts");
660 }
661 fontdirs = (String[])fontConfigDirs.toArray(new String[0]);
662 }
663
664 /* Called by MToolkit to set the X11 font path */
665 public static void setNativeFontPath() {
666 if (fontdirs == null) {
667 return;
668 }
669
670 // need to register these individually rather than by one call
671 // to ensure that one bad directory doesn't cause all to be rejected
672 for (int i=0; i<fontdirs.length; i++) {
673 if (debugFonts) {
674 logger.info("Add " + fontdirs[i] + " to X11 fontpath");
675 }
676 FontManager.setNativeFontPath(fontdirs[i]);
677 }
678 }
679
680 /* Register just the paths, (it doesn't register the fonts).
681 * If a font configuration file has specified a baseFontPath
682 * fontPath is just those directories, unless on usage we
683 * find it doesn't contain what we need for the logical fonts.
684 * Otherwise, we register all the paths on Solaris, because
685 * the fontPath we have here is the complete one from
686 * parsing /var/sadm/install/contents, not just
687 * what's on the X font path (may be this should be
688 * changed).
689 * But for now what it means is that if we didn't do
690 * this then if the font weren't listed anywhere on the
691 * less complete font path we'd trigger loadFonts which
692 * actually registers the fonts. This may actually be
693 * the right thing tho' since that would also set up
694 * the X font path without which we wouldn't be able to
695 * display some "native" fonts.
696 * So something to revisit is that probably fontPath
697 * here ought to be only the X font path + jre font dir.
698 * loadFonts should have a separate native call to
699 * get the rest of the platform font path.
700 *
701 * Registering the directories can now be avoided in the
702 * font configuration initialisation when filename entries
703 * exist in the font configuration file for all fonts.
704 * (Perhaps a little confusingly a filename entry is
705 * actually keyed using the XLFD used in the font entries,
706 * and it maps *to* a real filename).
707 * In the event any are missing, registration of all
708 * directories will be invoked to find the real files.
709 *
710 * But registering the directory performed other
711 * functions such as filling in the map of all native names
712 * for the font. So when this method isn't invoked, they still
713 * must be found. This is mitigated by getNativeNames now
714 * being able to return at least the platform name, but mostly
715 * by ensuring that when a filename key is found, that
716 * xlfd key is stored as one of the set of platform names
717 * for the font. Its a set because typical font configuration
718 * files reference the same CJK font files using multiple
719 * X11 encodings. For the code that adds this to the map
720 * see X11GE.getFileNameFromPlatformName(..)
721 * If you don't get all of these then some code points may
722 * not use the Xserver, and will not get the PCF bitmaps
723 * that are available for some point sizes.
724 * So, in the event that there is such a problem,
725 * unconditionally making this call may be necessary, at
726 * some cost to JRE start-up
727 */
728 protected void registerFontDirs(String pathName) {
729
730 StringTokenizer parser = new StringTokenizer(pathName,
731 File.pathSeparator);
732 try {
733 while (parser.hasMoreTokens()) {
734 String dirPath = parser.nextToken();
735 if (dirPath != null && !registeredDirs.containsKey(dirPath)) {
736 registeredDirs.put(dirPath, null);
737 registerFontDir(dirPath);
738 }
739 }
740 } catch (NoSuchElementException e) {
741 }
742 }
743
744 /* NOTE: this method needs to be executed in a privileged context.
745 * The superclass constructor which is the primary caller of
746 * this method executes entirely in such a context. Additionally
747 * the loadFonts() method does too. So all should be well.
748
749 */
750 protected void registerFontDir(String path) {
751 /* fonts.dir file format looks like :-
752 * 47
753 * Arial.ttf -monotype-arial-regular-r-normal--0-0-0-0-p-0-iso8859-1
754 * Arial-Bold.ttf -monotype-arial-bold-r-normal--0-0-0-0-p-0-iso8859-1
755 * ...
756 */
757 if (debugFonts) {
758 logger.info("ParseFontDir " + path);
759 }
760 File fontsDotDir = new File(path + File.separator + "fonts.dir");
761 FileReader fr = null;
762 try {
763 if (fontsDotDir.canRead()) {
764 fr = new FileReader(fontsDotDir);
765 BufferedReader br = new BufferedReader(fr, 8192);
766 StreamTokenizer st = new StreamTokenizer(br);
767 st.eolIsSignificant(true);
768 int ttype = st.nextToken();
769 if (ttype == StreamTokenizer.TT_NUMBER) {
770 int numEntries = (int)st.nval;
771 ttype = st.nextToken();
772 if (ttype == StreamTokenizer.TT_EOL) {
773 st.resetSyntax();
774 st.wordChars(32, 127);
775 st.wordChars(128 + 32, 255);
776 st.whitespaceChars(0, 31);
777
778 for (int i=0; i < numEntries; i++) {
779 ttype = st.nextToken();
780 if (ttype == StreamTokenizer.TT_EOF) {
781 break;
782 }
783 if (ttype != StreamTokenizer.TT_WORD) {
784 break;
785 }
786 int breakPos = st.sval.indexOf(' ');
787 if (breakPos <= 0) {
788 /* On TurboLinux 8.0 a fonts.dir file had
789 * a line with integer value "24" which
790 * appeared to be the number of remaining
791 * entries in the file. This didn't add to
792 * the value on the first line of the file.
793 * Seemed like XFree86 didn't like this line
794 * much either. It failed to parse the file.
795 * Ignore lines like this completely, and
796 * don't let them count as an entry.
797 */
798 numEntries++;
799 ttype = st.nextToken();
800 if (ttype != StreamTokenizer.TT_EOL) {
801 break;
802 }
803
804 continue;
805 }
806 if (st.sval.charAt(0) == '!') {
807 /* TurboLinux 8.0 comment line: ignore.
808 * can't use st.commentChar('!') to just
809 * skip because this line mustn't count
810 * against numEntries.
811 */
812 numEntries++;
813 ttype = st.nextToken();
814 if (ttype != StreamTokenizer.TT_EOL) {
815 break;
816 }
817 continue;
818 }
819 String fileName = st.sval.substring(0, breakPos);
820 /* TurboLinux 8.0 uses some additional syntax to
821 * indicate algorithmic styling values.
822 * Ignore ':' separated files at the beginning
823 * of the fileName
824 */
825 int lastColon = fileName.lastIndexOf(':');
826 if (lastColon > 0) {
827 if (lastColon+1 >= fileName.length()) {
828 continue;
829 }
830 fileName = fileName.substring(lastColon+1);
831 }
832 String fontPart = st.sval.substring(breakPos+1);
833 String fontID = specificFontIDForName(fontPart);
834 String sVal = (String) fontNameMap.get(fontID);
835
836 if (debugFonts) {
837 logger.info("file=" + fileName +
838 " xlfd=" + fontPart);
839 logger.info("fontID=" + fontID +
840 " sVal=" + sVal);
841 }
842 String fullPath = null;
843 try {
844 File file = new File(path,fileName);
845 /* we may have a resolved symbolic link
846 * this becomes important for an xlfd we
847 * still need to know the location it was
848 * found to update the X server font path
849 * for use by AWT heavyweights - and when 2D
850 * wants to use the native rasteriser.
851 */
852 if (xFontDirsMap == null) {
853 xFontDirsMap = new HashMap();
854 }
855 xFontDirsMap.put(fontID, path);
856 fullPath = file.getCanonicalPath();
857 } catch (IOException e) {
858 fullPath = path + File.separator + fileName;
859 }
860 Vector xVal = (Vector) xlfdMap.get(fullPath);
861 if (debugFonts) {
862 logger.info("fullPath=" + fullPath +
863 " xVal=" + xVal);
864 }
865 if ((xVal == null || !xVal.contains(fontPart)) &&
866 (sVal == null) || !sVal.startsWith("/")) {
867 if (debugFonts) {
868 logger.info("Map fontID:"+fontID +
869 "to file:" + fullPath);
870 }
871 fontNameMap.put(fontID, fullPath);
872 if (xVal == null) {
873 xVal = new Vector();
874 xlfdMap.put (fullPath, xVal);
875 }
876 xVal.add(fontPart);
877 }
878
879 ttype = st.nextToken();
880 if (ttype != StreamTokenizer.TT_EOL) {
881 break;
882 }
883 }
884 }
885 }
886 fr.close();
887 }
888 } catch (IOException ioe1) {
889 } finally {
890 if (fr != null) {
891 try {
892 fr.close();
893 } catch (IOException ioe2) {
894 }
895 }
896 }
897 }
898
899 @Override
900 public void loadFonts() {
901 super.loadFonts();
902 /* These maps are greatly expanded during a loadFonts but
903 * can be reset to their initial state afterwards.
904 * Since preferLocaleFonts() and preferProportionalFonts() will
905 * trigger a partial repopulating from the FontConfiguration
906 * it has to be the inital (empty) state for the latter two, not
907 * simply nulling out.
908 * xFontDirsMap is a special case in that the implementation
909 * will typically not ever need to initialise it so it can be null.
910 */
911 xFontDirsMap = null;
912 xlfdMap = new HashMap(1);
913 fontNameMap = new HashMap(1);
914 }
915
916 // Implements SunGraphicsEnvironment.createFontConfiguration.
917 protected FontConfiguration createFontConfiguration() {
918
919 /* The logic here decides whether to use a preconfigured
920 * fontconfig.properties file, or synthesise one using platform APIs.
921 * On Solaris (as opposed to OpenSolaris) we try to use the
922 * pre-configured ones, but if the files it specifies are missing
923 * we fail-safe to synthesising one. This might happen if Solaris
924 * changes its fonts.
925 * For OpenSolaris I don't expect us to ever create fontconfig files,
926 * so it will always synthesise. Note that if we misidentify
927 * OpenSolaris as Solaris, then the test for the presence of
928 * Solaris-only font files will correct this.
929 * For Linux we require an exact match of distro and version to
930 * use the preconfigured file, and also that it points to
931 * existent fonts.
932 * If synthesising fails, we fall back to any preconfigured file
933 * and do the best we can. For the commercial JDK this will be
934 * fine as it includes the Lucida fonts. OpenJDK should not hit
935 * this as the synthesis should always work on its platforms.
936 */
937 FontConfiguration mFontConfig = new MFontConfiguration(this);
938 if (isOpenSolaris ||
939 (isLinux &&
940 (!mFontConfig.foundOsSpecificFile() ||
941 !mFontConfig.fontFilesArePresent()) ||
942 (isSolaris && !mFontConfig.fontFilesArePresent()))) {
943 FcFontConfiguration fcFontConfig =
944 new FcFontConfiguration(this);
945 if (fcFontConfig.init()) {
946 return fcFontConfig;
947 }
948 }
949 mFontConfig.init();
950 return mFontConfig;
951 }
952 public FontConfiguration
953 createFontConfiguration(boolean preferLocaleFonts,
954 boolean preferPropFonts) {
955
956 FontConfiguration config = getFontConfiguration();
957 if (config instanceof FcFontConfiguration) {
958 // Doesn't need to implement the alternate support.
959 return config;
960 }
961
962 return new MFontConfiguration(this,
963 preferLocaleFonts, preferPropFonts);
964 }
965
966 /**
967 * Returns face name for default font, or null if
968 * no face names are used for CompositeFontDescriptors
969 * for this platform.
970 */
971 public String getDefaultFontFaceName() {
972
973 return null;
974 }
975
976 private static native boolean pRunningXinerama();
977 private static native Point getXineramaCenterPoint();
978
979 /**
980 * Override for Xinerama case: call new Solaris API for getting the correct
981 * centering point from the windowing system.
982 */
983 public Point getCenterPoint() {
984 if (runningXinerama()) {
|
51 import sun.java2d.SunGraphicsEnvironment;
52 import sun.java2d.SurfaceManagerFactory;
53 import sun.java2d.UnixSurfaceManagerFactory;
54
55 /**
56 * This is an implementation of a GraphicsEnvironment object for the
57 * default local GraphicsEnvironment used by the Java Runtime Environment
58 * for X11 environments.
59 *
60 * @see GraphicsDevice
61 * @see GraphicsConfiguration
62 */
63 public class X11GraphicsEnvironment
64 extends SunGraphicsEnvironment
65 {
66 private static final Logger log = Logger.getLogger("sun.awt.X11GraphicsEnvironment");
67 private static final Logger screenLog = Logger.getLogger("sun.awt.screen.X11GraphicsEnvironment");
68
69 private static Boolean xinerState;
70
71 static {
72 java.security.AccessController.doPrivileged(
73 new java.security.PrivilegedAction() {
74 public Object run() {
75 System.loadLibrary("awt");
76
77 /*
78 * Note: The MToolkit object depends on the static initializer
79 * of X11GraphicsEnvironment to initialize the connection to
80 * the X11 server.
81 */
82 if (!isHeadless()) {
83 // first check the OGL system property
84 boolean glxRequested = false;
85 String prop = System.getProperty("sun.java2d.opengl");
86 if (prop != null) {
87 if (prop.equals("true") || prop.equals("t")) {
88 glxRequested = true;
89 } else if (prop.equals("True") || prop.equals("T")) {
90 glxRequested = true;
146 */
147 private static native void initDisplay(boolean glxRequested);
148
149 public X11GraphicsEnvironment() {
150 }
151
152 protected native int getNumScreens();
153
154 protected GraphicsDevice makeScreenDevice(int screennum) {
155 return new X11GraphicsDevice(screennum);
156 }
157
158 protected native int getDefaultScreenNum();
159 /**
160 * Returns the default screen graphics device.
161 */
162 public GraphicsDevice getDefaultScreenDevice() {
163 return getScreenDevices()[getDefaultScreenNum()];
164 }
165
166 public boolean isDisplayLocal() {
167 if (isDisplayLocal == null) {
168 SunToolkit.awtLock();
169 try {
170 if (isDisplayLocal == null) {
171 isDisplayLocal = Boolean.valueOf(_isDisplayLocal());
172 }
173 } finally {
174 SunToolkit.awtUnlock();
175 }
176 }
177 return isDisplayLocal.booleanValue();
178 }
179
180 private static boolean _isDisplayLocal() {
181 if (isHeadless()) {
182 return true;
183 }
184
185 String isRemote = (String)java.security.AccessController.doPrivileged(
222 } catch (SocketException e1) {
223 System.err.println(e1.getMessage());
224 return Boolean.FALSE;
225 }
226
227 for (; interfaces.hasMoreElements();) {
228 locals = ((NetworkInterface)interfaces.nextElement()).getInetAddresses();
229 for (; locals.hasMoreElements();) {
230 for (int i = 0; i < remAddr.length; i++) {
231 if (locals.nextElement().equals(remAddr[i])) {
232 return Boolean.TRUE;
233 }
234 }
235 }
236 }
237 return Boolean.FALSE;
238 }});
239 return result.booleanValue();
240 }
241
242
243
244 /**
245 * Returns face name for default font, or null if
246 * no face names are used for CompositeFontDescriptors
247 * for this platform.
248 */
249 public String getDefaultFontFaceName() {
250
251 return null;
252 }
253
254 private static native boolean pRunningXinerama();
255 private static native Point getXineramaCenterPoint();
256
257 /**
258 * Override for Xinerama case: call new Solaris API for getting the correct
259 * centering point from the windowing system.
260 */
261 public Point getCenterPoint() {
262 if (runningXinerama()) {
|