src/solaris/classes/sun/awt/X11GraphicsEnvironment.java

Print this page
rev 1379 : [mq]: fontmanager.patch


  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()) {