Source Code Cross Referenced for X11GraphicsEnvironment.java in  » 6.0-JDK-Platform » solaris » sun » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Platform » solaris » sun.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.awt;
0027:
0028:        import java.awt.GraphicsDevice;
0029:        import java.awt.Point;
0030:        import java.awt.Rectangle;
0031:        import java.io.BufferedReader;
0032:        import java.io.File;
0033:        import java.io.FileReader;
0034:        import java.io.FileNotFoundException;
0035:        import java.io.InputStream;
0036:        import java.io.IOException;
0037:        import java.io.StreamTokenizer;
0038:        import java.net.InetAddress;
0039:        import java.net.NetworkInterface;
0040:        import java.net.SocketException;
0041:        import java.net.UnknownHostException;
0042:        import java.util.Enumeration;
0043:        import java.util.HashMap;
0044:        import java.util.HashSet;
0045:        import java.util.Iterator;
0046:        import java.util.Locale;
0047:        import java.util.List;
0048:        import java.util.Map;
0049:        import java.util.NoSuchElementException;
0050:        import java.util.StringTokenizer;
0051:        import java.util.TreeMap;
0052:        import java.util.Vector;
0053:        import sun.awt.motif.MFontConfiguration;
0054:        import sun.font.Font2D;
0055:        import sun.font.FontManager;
0056:        import sun.font.NativeFont;
0057:        import sun.java2d.SunGraphicsEnvironment;
0058:
0059:        /**
0060:         * This is an implementation of a GraphicsEnvironment object for the
0061:         * default local GraphicsEnvironment used by the Java Runtime Environment
0062:         * for X11 environments.
0063:         *
0064:         * @see GraphicsDevice
0065:         * @see GraphicsConfiguration
0066:         * @version 1.77 05/05/07
0067:         */
0068:        public class X11GraphicsEnvironment extends SunGraphicsEnvironment {
0069:            private static final DebugHelper dbg = DebugHelper
0070:                    .create(X11GraphicsEnvironment.class);
0071:            private static Boolean xinerState;
0072:
0073:            /*
0074:             * This is the set of font directories needed to be on the X font path
0075:             * to enable AWT heavyweights to find all of the font configuration fonts.
0076:             * It is populated by :
0077:             * - awtfontpath entries in the fontconfig.properties
0078:             * - parent directories of "core" fonts used in the fontconfig.properties
0079:             * - looking up font dirs in the xFontDirsMap where the key is a fontID
0080:             *   (cut down version of the XLFD read from the font configuration file).
0081:             * This set is nulled out after use to free heap space.
0082:             */
0083:            private static HashSet<String> fontConfigDirs = null;
0084:
0085:            /*
0086:             * fontNameMap is a map from a fontID (which is a substring of an XLFD like
0087:             * "-monotype-arial-bold-r-normal-iso8859-7")
0088:             * to font file path like
0089:             * /usr/openwin/lib/locale/iso_8859_7/X11/fonts/TrueType/ArialBoldItalic.ttf
0090:             * It's used in a couple of methods like
0091:             * getFileNameFomPlatformName(..) to help locate the font file.
0092:             * We use this substring of a full XLFD because the font configuration files
0093:             * define the XLFDs in a way that's easier to make into a request.
0094:             * E.g., the -0-0-0-0-p-0- reported by X is -*-%d-*-*-p-*- in the font
0095:             * configuration files. We need to remove that part for comparisons.
0096:             */
0097:            private static Map fontNameMap = new HashMap();
0098:
0099:            /* xFontDirsMap is also a map from a font ID to a font filepath.
0100:             * The difference from fontNameMap is just that it does not have
0101:             * resolved symbolic links. Normally this is not interesting except
0102:             * that we need to know the directory in which a font was found to
0103:             * add it to the X font server path, since although the files may
0104:             * be linked, the fonts.dir is different and specific to the encoding
0105:             * handled by that directory. This map is nulled out after use to free
0106:             * heap space. If the optimal path is taken, such that all fonts in
0107:             * font configuration files are referenced by filename, then the font
0108:             * dir can be directly derived as its parent directory.
0109:             * If a font is used by two XLFDs, each corresponding to a different
0110:             * X11 font directory, then precautions must be taken to include both
0111:             * directories. 
0112:             */
0113:            private static Map xFontDirsMap;
0114:
0115:            /*
0116:             * xlfdMap is a map from a platform path like
0117:             * /usr/openwin/lib/locale/ja/X11/fonts/TT/HG-GothicB.ttf to an XLFD like
0118:             * "-ricoh-hg gothic b-medium-r-normal--0-0-0-0-m-0-jisx0201.1976-0"
0119:             * Because there may be multiple native names, because the font is used
0120:             * to support multiple X encodings for example, the value of an entry in
0121:             * this map is always a vector where we store all the native names.
0122:             * For fonts which we don't understand the key isn't a pathname, its
0123:             * the full XLFD string like :-
0124:             * "-ricoh-hg gothic b-medium-r-normal--0-0-0-0-m-0-jisx0201.1976-0"
0125:             */
0126:            private static Map xlfdMap = new HashMap();
0127:
0128:            /*
0129:             * Used to eliminate redundant work. When a font directory is
0130:             * registered it added to this list. Subsequent registrations for the
0131:             * same directory can then be skipped by checking this Map.
0132:             * Access to this map is not synchronised here since creation
0133:             * of the singleton GE instance is already synchronised and that is
0134:             * the only code path that accesses this map.
0135:             */
0136:            private static HashMap registeredDirs = new HashMap();
0137:
0138:            /* Array of directories to be added to the X11 font path.
0139:             * Used by static method called from Toolkits which use X11 fonts.
0140:             * Specifically this means MToolkit
0141:             */
0142:            private static String[] fontdirs = null;
0143:
0144:            static {
0145:                java.security.AccessController
0146:                        .doPrivileged(new java.security.PrivilegedAction() {
0147:                            public Object run() {
0148:                                System.loadLibrary("awt");
0149:
0150:                                /*
0151:                                 * Note: The MToolkit object depends on the static initializer
0152:                                 * of X11GraphicsEnvironment to initialize the connection to
0153:                                 * the X11 server.
0154:                                 */
0155:                                if (!isHeadless()) {
0156:                                    // first check the OGL system property
0157:                                    boolean glxRequested = false;
0158:                                    String prop = System
0159:                                            .getProperty("sun.java2d.opengl");
0160:                                    if (prop != null) {
0161:                                        if (prop.equals("true")
0162:                                                || prop.equals("t")) {
0163:                                            glxRequested = true;
0164:                                        } else if (prop.equals("True")
0165:                                                || prop.equals("T")) {
0166:                                            glxRequested = true;
0167:                                            glxVerbose = true;
0168:                                        }
0169:                                    }
0170:
0171:                                    // initialize the X11 display connection
0172:                                    initDisplay(glxRequested);
0173:
0174:                                    // only attempt to initialize GLX if it was requested
0175:                                    if (glxRequested) {
0176:                                        glxAvailable = initGLX();
0177:                                        if (glxVerbose && !glxAvailable) {
0178:                                            System.out
0179:                                                    .println("Could not enable OpenGL "
0180:                                                            + "pipeline (GLX 1.3 not available)");
0181:                                        }
0182:                                    }
0183:                                }
0184:
0185:                                return null;
0186:                            }
0187:                        });
0188:            }
0189:
0190:            private static boolean glxAvailable;
0191:            private static boolean glxVerbose;
0192:
0193:            private static native boolean initGLX();
0194:
0195:            public static boolean isGLXAvailable() {
0196:                return glxAvailable;
0197:            }
0198:
0199:            public static boolean isGLXVerbose() {
0200:                return glxVerbose;
0201:            }
0202:
0203:            /**
0204:             * Checks if Shared Memory extension can be used.
0205:             * Returns:
0206:             *	 -1 if server doesn't support MITShm
0207:             *	  1 if server supports it and it can be used
0208:             *	  0 otherwise
0209:             */
0210:            private static native int checkShmExt();
0211:
0212:            private static native String getDisplayString();
0213:
0214:            private static Boolean isDisplayLocal;
0215:
0216:            /**
0217:             * This should only be called from the static initializer, so no need for
0218:             * the synchronized keyword.
0219:             */
0220:            private static native void initDisplay(boolean glxRequested);
0221:
0222:            public X11GraphicsEnvironment() {
0223:            }
0224:
0225:            protected native int getNumScreens();
0226:
0227:            protected GraphicsDevice makeScreenDevice(int screennum) {
0228:                return new X11GraphicsDevice(screennum);
0229:            }
0230:
0231:            protected native int getDefaultScreenNum();
0232:
0233:            /**
0234:             * Returns the default screen graphics device.
0235:             */
0236:            public GraphicsDevice getDefaultScreenDevice() {
0237:                return getScreenDevices()[getDefaultScreenNum()];
0238:            }
0239:
0240:            public static boolean isDisplayLocal() {
0241:                if (isDisplayLocal == null) {
0242:                    SunToolkit.awtLock();
0243:                    try {
0244:                        if (isDisplayLocal == null) {
0245:                            isDisplayLocal = Boolean.valueOf(_isDisplayLocal());
0246:                        }
0247:                    } finally {
0248:                        SunToolkit.awtUnlock();
0249:                    }
0250:                }
0251:                return isDisplayLocal.booleanValue();
0252:            }
0253:
0254:            private static boolean _isDisplayLocal() {
0255:                if (isHeadless()) {
0256:                    return true;
0257:                }
0258:
0259:                String isRemote = (String) java.security.AccessController
0260:                        .doPrivileged(new sun.security.action.GetPropertyAction(
0261:                                "sun.java2d.remote"));
0262:                if (isRemote != null) {
0263:                    return isRemote.equals("false");
0264:                }
0265:
0266:                int shm = checkShmExt();
0267:                if (shm != -1) {
0268:                    return (shm == 1);
0269:                }
0270:
0271:                // If XServer doesn't support ShMem extension, 
0272:                // try the other way
0273:
0274:                String display = getDisplayString();
0275:                int ind = display.indexOf(':');
0276:                final String hostName = display.substring(0, ind);
0277:                if (ind <= 0) {
0278:                    // ':0' case
0279:                    return true;
0280:                }
0281:
0282:                Boolean result = (Boolean) java.security.AccessController
0283:                        .doPrivileged(new java.security.PrivilegedAction() {
0284:                            public Object run() {
0285:                                InetAddress remAddr[] = null;
0286:                                Enumeration locals = null;
0287:                                Enumeration interfaces = null;
0288:                                try {
0289:                                    interfaces = NetworkInterface
0290:                                            .getNetworkInterfaces();
0291:                                    remAddr = InetAddress
0292:                                            .getAllByName(hostName);
0293:                                    if (remAddr == null) {
0294:                                        return Boolean.FALSE;
0295:                                    }
0296:                                } catch (UnknownHostException e) {
0297:                                    System.err.println("Unknown host: "
0298:                                            + hostName);
0299:                                    return Boolean.FALSE;
0300:                                } catch (SocketException e1) {
0301:                                    System.err.println(e1.getMessage());
0302:                                    return Boolean.FALSE;
0303:                                }
0304:
0305:                                for (; interfaces.hasMoreElements();) {
0306:                                    locals = ((NetworkInterface) interfaces
0307:                                            .nextElement()).getInetAddresses();
0308:                                    for (; locals.hasMoreElements();) {
0309:                                        for (int i = 0; i < remAddr.length; i++) {
0310:                                            if (locals.nextElement().equals(
0311:                                                    remAddr[i])) {
0312:                                                return Boolean.TRUE;
0313:                                            }
0314:                                        }
0315:                                    }
0316:                                }
0317:                                return Boolean.FALSE;
0318:                            }
0319:                        });
0320:                return result.booleanValue();
0321:            }
0322:
0323:            /* These maps are used on Linux where we reference the Lucida oblique
0324:             * fonts in fontconfig files even though they aren't in the standard
0325:             * font directory. This explicitly remaps the XLFDs for these to the
0326:             * correct base font. This is needed to prevent composite fonts from
0327:             * defaulting to the Lucida Sans which is a bad substitute for the
0328:             * monospaced Lucida Sans Typewriter. Also these maps prevent the
0329:             * JRE from doing wasted work at start up.
0330:             */
0331:            HashMap<String, String> oblmap = null;
0332:
0333:            private String getObliqueLucidaFontID(String fontID) {
0334:                if (fontID.startsWith("-lucidasans-medium-i-normal")
0335:                        || fontID.startsWith("-lucidasans-bold-i-normal")
0336:                        || fontID
0337:                                .startsWith("-lucidatypewriter-medium-i-normal")
0338:                        || fontID.startsWith("-lucidatypewriter-bold-i-normal")) {
0339:                    return fontID.substring(0, fontID.indexOf("-i-"));
0340:                } else {
0341:                    return null;
0342:                }
0343:            }
0344:
0345:            private void initObliqueLucidaFontMap() {
0346:                oblmap = new HashMap<String, String>();
0347:                oblmap.put("-lucidasans-medium", jreLibDirName
0348:                        + "/fonts/LucidaSansRegular.ttf");
0349:                oblmap.put("-lucidasans-bold", jreLibDirName
0350:                        + "/fonts/LucidaSansDemiBold.ttf");
0351:                oblmap.put("-lucidatypewriter-medium", jreLibDirName
0352:                        + "/fonts/LucidaTypewriterRegular.ttf");
0353:                oblmap.put("-lucidatypewriter-bold", jreLibDirName
0354:                        + "/fonts/LucidaTypewriterBold.ttf");
0355:            }
0356:
0357:            /**
0358:             * Takes family name property in the following format:
0359:             * "-linotype-helvetica-medium-r-normal-sans-*-%d-*-*-p-*-iso8859-1"
0360:             * and returns the name of the corresponding physical font.
0361:             * This code is used to resolve font configuration fonts, and expects
0362:             * only to get called for these fonts. 
0363:             */
0364:            public String getFileNameFromPlatformName(String platName) {
0365:                String fileName = null;
0366:                String fontID = specificFontIDForName(platName);
0367:
0368:                /* If the font filename has been explicitly assigned in the
0369:                 * font configuration file, use it. This avoids accessing
0370:                 * the wrong fonts on Linux, where different fonts (some
0371:                 * of which may not be usable by 2D) may share the same
0372:                 * specific font ID. It may also speed up the lookup.
0373:                 */
0374:                fileName = super .getFileNameFromPlatformName(platName);
0375:                if (fileName != null) {
0376:                    if (isHeadless() && fileName.startsWith("-")) {
0377:                        /* if it's headless, no xlfd should be used */
0378:                        return null;
0379:                    }
0380:                    if (fileName.startsWith("/")) {
0381:                        /* If a path is assigned in the font configuration file,
0382:                         * it is required that the config file also specify using the
0383:                         * new awtfontpath key the X11 font directories
0384:                         * which must be added to the X11 font path to support
0385:                         * AWT access to that font. For that reason we no longer
0386:                         * have code here to add the parent directory to the list
0387:                         * of font config dirs, since the parent directory may not
0388:                         * be sufficient if fonts are symbolically linked to a
0389:                         * different directory.
0390:                         *
0391:                         * Add this XLFD (platform name) to the list of known
0392:                         * ones for this file.
0393:                         */
0394:                        Vector xVal = (Vector) xlfdMap.get(fileName);
0395:                        if (xVal == null) {
0396:                            /* Try to be robust on Linux distros which move fonts
0397:                             * around by verifying that the fileName represents a
0398:                             * file that exists.  If it doesn't, set it to null
0399:                             * to trigger a search.
0400:                             */
0401:                            if (getFontConfiguration().needToSearchForFile(
0402:                                    fileName)) {
0403:                                fileName = null;
0404:                            }
0405:                            if (fileName != null) {
0406:                                xVal = new Vector();
0407:                                xVal.add(platName);
0408:                                xlfdMap.put(fileName, xVal);
0409:                            }
0410:                        } else {
0411:                            if (!xVal.contains(platName)) {
0412:                                xVal.add(platName);
0413:                            }
0414:                        }
0415:                    }
0416:                    if (fileName != null) {
0417:                        fontNameMap.put(fontID, fileName);
0418:                        return fileName;
0419:                    }
0420:                }
0421:
0422:                if (fontID != null) {
0423:                    fileName = (String) fontNameMap.get(fontID);
0424:                    /* On Linux check for the Lucida Oblique fonts */
0425:                    if (fileName == null && isLinux && !isOpenJDK()) {
0426:                        if (oblmap == null) {
0427:                            initObliqueLucidaFontMap();
0428:                        }
0429:                        String oblkey = getObliqueLucidaFontID(fontID);
0430:                        if (oblkey != null) {
0431:                            fileName = oblmap.get(oblkey);
0432:                        }
0433:                    }
0434:                    if (fontPath == null
0435:                            && (fileName == null || !fileName.startsWith("/"))) {
0436:                        if (debugFonts) {
0437:                            logger
0438:                                    .warning("** Registering all font paths because "
0439:                                            + "can't find file for " + platName);
0440:                        }
0441:                        fontPath = getPlatformFontPath(noType1Font);
0442:                        registerFontDirs(fontPath);
0443:                        if (debugFonts) {
0444:                            logger
0445:                                    .warning("** Finished registering all font paths");
0446:                        }
0447:                        fileName = (String) fontNameMap.get(fontID);
0448:                    }
0449:                    if (fileName == null && !isHeadless()) {
0450:                        /* Query X11 directly to see if this font is available
0451:                         * as a native font.
0452:                         */
0453:                        fileName = getX11FontName(platName);
0454:                    }
0455:                    if (fileName == null) {
0456:                        fontID = switchFontIDForName(platName);
0457:                        fileName = (String) fontNameMap.get(fontID);
0458:                    }
0459:                    if (fileName != null) {
0460:                        fontNameMap.put(fontID, fileName);
0461:                    }
0462:                }
0463:                return fileName;
0464:            }
0465:
0466:            private static String getX11FontName(String platName) {
0467:                String xlfd = platName.replaceAll("%d", "*");
0468:                if (NativeFont.fontExists(xlfd)) {
0469:                    return xlfd;
0470:                } else {
0471:                    return null;
0472:                }
0473:            }
0474:
0475:            /**
0476:             * Returns the face name for the given XLFD.
0477:             */
0478:            public String getFileNameFromXLFD(String name) {
0479:                String fileName = null;
0480:                String fontID = specificFontIDForName(name);
0481:                if (fontID != null) {
0482:                    fileName = (String) fontNameMap.get(fontID);
0483:                    if (fileName == null) {
0484:                        fontID = switchFontIDForName(name);
0485:                        fileName = (String) fontNameMap.get(fontID);
0486:                    }
0487:                    if (fileName == null) {
0488:                        fileName = getDefaultFontFile();
0489:                    }
0490:                }
0491:                return fileName;
0492:            }
0493:
0494:            // constants identifying XLFD and font ID fields
0495:            private static final int FOUNDRY_FIELD = 1;
0496:            private static final int FAMILY_NAME_FIELD = 2;
0497:            private static final int WEIGHT_NAME_FIELD = 3;
0498:            private static final int SLANT_FIELD = 4;
0499:            private static final int SETWIDTH_NAME_FIELD = 5;
0500:            private static final int ADD_STYLE_NAME_FIELD = 6;
0501:            private static final int PIXEL_SIZE_FIELD = 7;
0502:            private static final int POINT_SIZE_FIELD = 8;
0503:            private static final int RESOLUTION_X_FIELD = 9;
0504:            private static final int RESOLUTION_Y_FIELD = 10;
0505:            private static final int SPACING_FIELD = 11;
0506:            private static final int AVERAGE_WIDTH_FIELD = 12;
0507:            private static final int CHARSET_REGISTRY_FIELD = 13;
0508:            private static final int CHARSET_ENCODING_FIELD = 14;
0509:
0510:            private String switchFontIDForName(String name) {
0511:
0512:                int[] hPos = new int[14];
0513:                int hyphenCnt = 1;
0514:                int pos = 1;
0515:
0516:                while (pos != -1 && hyphenCnt < 14) {
0517:                    pos = name.indexOf('-', pos);
0518:                    if (pos != -1) {
0519:                        hPos[hyphenCnt++] = pos;
0520:                        pos++;
0521:                    }
0522:                }
0523:
0524:                if (hyphenCnt != 14) {
0525:                    if (debugFonts) {
0526:                        logger
0527:                                .severe("Font Configuration Font ID is malformed:"
0528:                                        + name);
0529:                    }
0530:                    return name; // what else can we do?
0531:                }
0532:
0533:                String slant = name.substring(hPos[SLANT_FIELD - 1] + 1,
0534:                        hPos[SLANT_FIELD]);
0535:                String family = name.substring(hPos[FAMILY_NAME_FIELD - 1] + 1,
0536:                        hPos[FAMILY_NAME_FIELD]);
0537:                String registry = name.substring(
0538:                        hPos[CHARSET_REGISTRY_FIELD - 1] + 1,
0539:                        hPos[CHARSET_REGISTRY_FIELD]);
0540:                String encoding = name
0541:                        .substring(hPos[CHARSET_ENCODING_FIELD - 1] + 1);
0542:
0543:                if (slant.equals("i")) {
0544:                    slant = "o";
0545:                } else if (slant.equals("o")) {
0546:                    slant = "i";
0547:                }
0548:                // workaround for #4471000
0549:                if (family.equals("itc zapfdingbats") && registry.equals("sun")
0550:                        && encoding.equals("fontspecific")) {
0551:                    registry = "adobe";
0552:                }
0553:                StringBuffer sb = new StringBuffer(name.substring(
0554:                        hPos[FAMILY_NAME_FIELD - 1], hPos[SLANT_FIELD - 1] + 1));
0555:                sb.append(slant);
0556:                sb.append(name.substring(hPos[SLANT_FIELD],
0557:                        hPos[SETWIDTH_NAME_FIELD] + 1));
0558:                sb.append(registry);
0559:                sb.append(name.substring(hPos[CHARSET_ENCODING_FIELD - 1]));
0560:                String retval = sb.toString().toLowerCase(Locale.ENGLISH);
0561:                return retval;
0562:            }
0563:
0564:            private String specificFontIDForName(String name) {
0565:
0566:                int[] hPos = new int[14];
0567:                int hyphenCnt = 1;
0568:                int pos = 1;
0569:
0570:                while (pos != -1 && hyphenCnt < 14) {
0571:                    pos = name.indexOf('-', pos);
0572:                    if (pos != -1) {
0573:                        hPos[hyphenCnt++] = pos;
0574:                        pos++;
0575:                    }
0576:                }
0577:
0578:                if (hyphenCnt != 14) {
0579:                    if (debugFonts) {
0580:                        logger
0581:                                .severe("Font Configuration Font ID is malformed:"
0582:                                        + name);
0583:                    }
0584:                    return name; // what else can we do?
0585:                }
0586:
0587:                StringBuffer sb = new StringBuffer(name.substring(
0588:                        hPos[FAMILY_NAME_FIELD - 1], hPos[SETWIDTH_NAME_FIELD]));
0589:                sb.append(name.substring(hPos[CHARSET_REGISTRY_FIELD - 1]));
0590:                String retval = sb.toString().toLowerCase(Locale.ENGLISH);
0591:                return retval;
0592:            }
0593:
0594:            protected String[] getNativeNames(String fontFileName,
0595:                    String platformName) {
0596:                Vector nativeNames;
0597:                if ((nativeNames = (Vector) xlfdMap.get(fontFileName)) == null) {
0598:                    if (platformName == null) {
0599:                        return null;
0600:                    } else {
0601:                        /* back-stop so that at least the name used in the
0602:                         * font configuration file is known as a native name
0603:                         */
0604:                        String[] natNames = new String[1];
0605:                        natNames[0] = platformName;
0606:                        return natNames;
0607:                    }
0608:                } else {
0609:                    int len = nativeNames.size();
0610:                    return (String[]) nativeNames.toArray(new String[len]);
0611:                }
0612:            }
0613:
0614:            // An X font spec (xlfd) includes an encoding. The same TrueType font file
0615:            // may be referenced from different X font directories in font.dir files
0616:            // to support use in multiple encodings by X apps.
0617:            // So for the purposes of font configuration logical fonts where AWT
0618:            // heavyweights need to access the font via X APIs we need to ensure that
0619:            // the directory for precisely the encodings needed by this are added to
0620:            // the x font path. This requires that we note the platform names
0621:            // specified in font configuration files and use that to identify the
0622:            // X font directory that contains a font.dir file for that platform name
0623:            // and add it to the X font path (if display is local)
0624:            // Here we make use of an already built map of xlfds to font locations
0625:            // to add the font location to the set of those required to build the
0626:            // x font path needed by AWT.
0627:            // These are added to the x font path later.
0628:            // All this is necessary because on Solaris the font.dir directories
0629:            // may contain not real font files, but symbolic links to the actual
0630:            // location but that location is not suitable for the x font path, since
0631:            // it probably doesn't have a font.dir at all and certainly not one
0632:            // with the required encodings
0633:            // If the fontconfiguration file is properly set up so that all fonts
0634:            // are mapped to files then we will never trigger initialising
0635:            // xFontDirsMap (it will be null). In this case the awtfontpath entries
0636:            // must specify all the X11 directories needed by AWT.
0637:            protected void addFontToPlatformFontPath(String platformName) {
0638:                if (xFontDirsMap != null) {
0639:                    String fontID = specificFontIDForName(platformName);
0640:                    String dirName = (String) xFontDirsMap.get(fontID);
0641:                    if (dirName != null) {
0642:                        fontConfigDirs.add(dirName);
0643:                    }
0644:                }
0645:                return;
0646:            }
0647:
0648:            protected void getPlatformFontPathFromFontConfig() {
0649:                if (fontConfigDirs == null) {
0650:                    fontConfigDirs = getFontConfiguration().getAWTFontPathSet();
0651:                    if (debugFonts && fontConfigDirs != null) {
0652:                        String[] names = fontConfigDirs.toArray(new String[0]);
0653:                        for (int i = 0; i < names.length; i++) {
0654:                            logger.info("awtfontpath : " + names[i]);
0655:                        }
0656:                    }
0657:                }
0658:            }
0659:
0660:            protected void registerPlatformFontsUsedByFontConfiguration() {
0661:                if (fontConfigDirs == null) {
0662:                    return;
0663:                }
0664:                if (isLinux) {
0665:                    fontConfigDirs.add(jreLibDirName + File.separator
0666:                            + "oblique-fonts");
0667:                }
0668:                fontdirs = (String[]) fontConfigDirs.toArray(new String[0]);
0669:            }
0670:
0671:            /* Called by MToolkit to set the X11 font path */
0672:            public static void setNativeFontPath() {
0673:                if (fontdirs == null) {
0674:                    return;
0675:                }
0676:
0677:                // need to register these individually rather than by one call
0678:                // to ensure that one bad directory doesn't cause all to be rejected
0679:                for (int i = 0; i < fontdirs.length; i++) {
0680:                    if (debugFonts) {
0681:                        logger.info("Add " + fontdirs[i] + " to X11 fontpath");
0682:                    }
0683:                    FontManager.setNativeFontPath(fontdirs[i]);
0684:                }
0685:            }
0686:
0687:            /* Register just the paths, (it doesn't register the fonts).
0688:             * If a font configuration file has specified a baseFontPath
0689:             * fontPath is just those directories, unless on usage we
0690:             * find it doesn't contain what we need for the logical fonts.
0691:             * Otherwise, we register all the paths on Solaris, because
0692:             * the fontPath we have here is the complete one from
0693:             * parsing /var/sadm/install/contents, not just
0694:             * what's on the X font path (may be this should be
0695:             * changed).
0696:             * But for now what it means is that if we didn't do
0697:             * this then if the font weren't listed anywhere on the
0698:             * less complete font path we'd trigger loadFonts which
0699:             * actually registers the fonts. This may actually be
0700:             * the right thing tho' since that would also set up
0701:             * the X font path without which we wouldn't be able to
0702:             * display some "native" fonts.
0703:             * So something to revisit is that probably fontPath
0704:             * here ought to be only the X font path + jre font dir.
0705:             * loadFonts should have a separate native call to
0706:             * get the rest of the platform font path.
0707:             *
0708:             * Registering the directories can now be avoided in the
0709:             * font configuration initialisation when filename entries
0710:             * exist in the font configuration file for all fonts.
0711:             * (Perhaps a little confusingly a filename entry is
0712:             * actually keyed using the XLFD used in the font entries,
0713:             * and it maps *to* a real filename).
0714:             * In the event any are missing, registration of all
0715:             * directories will be invoked to find the real files.
0716:             *
0717:             * But registering the directory performed other
0718:             * functions such as filling in the map of all native names
0719:             * for the font. So when this method isn't invoked, they still
0720:             * must be found. This is mitigated by getNativeNames now
0721:             * being able to return at least the platform name, but mostly
0722:             * by ensuring that when a filename key is found, that
0723:             * xlfd key is stored as one of the set of platform names
0724:             * for the font. Its a set because typical font configuration
0725:             * files reference the same CJK font files using multiple
0726:             * X11 encodings. For the code that adds this to the map
0727:             * see X11GE.getFileNameFromPlatformName(..)
0728:             * If you don't get all of these then some code points may
0729:             * not use the Xserver, and will not get the PCF bitmaps
0730:             * that are available for some point sizes. 
0731:             * So, in the event that there is such a problem,
0732:             * unconditionally making this call may be necessary, at
0733:             * some cost to JRE start-up
0734:             */
0735:            protected void registerFontDirs(String pathName) {
0736:
0737:                StringTokenizer parser = new StringTokenizer(pathName,
0738:                        File.pathSeparator);
0739:                try {
0740:                    while (parser.hasMoreTokens()) {
0741:                        String dirPath = parser.nextToken();
0742:                        if (dirPath != null
0743:                                && !registeredDirs.containsKey(dirPath)) {
0744:                            registeredDirs.put(dirPath, null);
0745:                            registerFontDir(dirPath);
0746:                        }
0747:                    }
0748:                } catch (NoSuchElementException e) {
0749:                }
0750:            }
0751:
0752:            /* NOTE: this method needs to be executed in a privileged context.
0753:             * The superclass constructor which is the primary caller of
0754:             * this method executes entirely in such a context. Additionally
0755:             * the loadFonts() method does too. So all should be well.
0756:
0757:             */
0758:            protected void registerFontDir(String path) {
0759:                /* fonts.dir file format looks like :-
0760:                 * 47
0761:                 * Arial.ttf -monotype-arial-regular-r-normal--0-0-0-0-p-0-iso8859-1
0762:                 * Arial-Bold.ttf -monotype-arial-bold-r-normal--0-0-0-0-p-0-iso8859-1
0763:                 * ...
0764:                 */
0765:                if (debugFonts) {
0766:                    logger.info("ParseFontDir " + path);
0767:                }
0768:                File fontsDotDir = new File(path + File.separator + "fonts.dir");
0769:                FileReader fr = null;
0770:                try {
0771:                    if (fontsDotDir.canRead()) {
0772:                        fr = new FileReader(fontsDotDir);
0773:                        BufferedReader br = new BufferedReader(fr, 8192);
0774:                        StreamTokenizer st = new StreamTokenizer(br);
0775:                        st.eolIsSignificant(true);
0776:                        int ttype = st.nextToken();
0777:                        if (ttype == StreamTokenizer.TT_NUMBER) {
0778:                            int numEntries = (int) st.nval;
0779:                            ttype = st.nextToken();
0780:                            if (ttype == StreamTokenizer.TT_EOL) {
0781:                                st.resetSyntax();
0782:                                st.wordChars(32, 127);
0783:                                st.wordChars(128 + 32, 255);
0784:                                st.whitespaceChars(0, 31);
0785:
0786:                                for (int i = 0; i < numEntries; i++) {
0787:                                    ttype = st.nextToken();
0788:                                    if (ttype == StreamTokenizer.TT_EOF) {
0789:                                        break;
0790:                                    }
0791:                                    if (ttype != StreamTokenizer.TT_WORD) {
0792:                                        break;
0793:                                    }
0794:                                    int breakPos = st.sval.indexOf(' ');
0795:                                    if (breakPos <= 0) {
0796:                                        /* On TurboLinux 8.0 a fonts.dir file had
0797:                                         * a line with integer value "24" which
0798:                                         * appeared to be the number of remaining
0799:                                         * entries in the file. This didn't add to
0800:                                         * the value on the first line of the file.
0801:                                         * Seemed like XFree86 didn't like this line
0802:                                         * much either. It failed to parse the file.
0803:                                         * Ignore lines like this completely, and
0804:                                         * don't let them count as an entry.
0805:                                         */
0806:                                        numEntries++;
0807:                                        ttype = st.nextToken();
0808:                                        if (ttype != StreamTokenizer.TT_EOL) {
0809:                                            break;
0810:                                        }
0811:
0812:                                        continue;
0813:                                    }
0814:                                    if (st.sval.charAt(0) == '!') {
0815:                                        /* TurboLinux 8.0 comment line: ignore.
0816:                                         * can't use st.commentChar('!') to just
0817:                                         * skip because this line mustn't count
0818:                                         * against numEntries.
0819:                                         */
0820:                                        numEntries++;
0821:                                        ttype = st.nextToken();
0822:                                        if (ttype != StreamTokenizer.TT_EOL) {
0823:                                            break;
0824:                                        }
0825:                                        continue;
0826:                                    }
0827:                                    String fileName = st.sval.substring(0,
0828:                                            breakPos);
0829:                                    /* TurboLinux 8.0 uses some additional syntax to
0830:                                     * indicate algorithmic styling values.
0831:                                     * Ignore ':' separated files at the beginning
0832:                                     * of the fileName
0833:                                     */
0834:                                    int lastColon = fileName.lastIndexOf(':');
0835:                                    if (lastColon > 0) {
0836:                                        if (lastColon + 1 >= fileName.length()) {
0837:                                            continue;
0838:                                        }
0839:                                        fileName = fileName
0840:                                                .substring(lastColon + 1);
0841:                                    }
0842:                                    String fontPart = st.sval
0843:                                            .substring(breakPos + 1);
0844:                                    String fontID = specificFontIDForName(fontPart);
0845:                                    String sVal = (String) fontNameMap
0846:                                            .get(fontID);
0847:
0848:                                    if (debugFonts) {
0849:                                        logger.info("file=" + fileName
0850:                                                + " xlfd=" + fontPart);
0851:                                        logger.info("fontID=" + fontID
0852:                                                + " sVal=" + sVal);
0853:                                    }
0854:                                    String fullPath = null;
0855:                                    try {
0856:                                        File file = new File(path, fileName);
0857:                                        /* we may have a resolved symbolic link
0858:                                         * this becomes important for an xlfd we
0859:                                         * still need to know the location it was
0860:                                         * found to update the X server font path
0861:                                         * for use by AWT heavyweights - and when 2D
0862:                                         * wants to use the native rasteriser.
0863:                                         */
0864:                                        if (xFontDirsMap == null) {
0865:                                            xFontDirsMap = new HashMap();
0866:                                        }
0867:                                        xFontDirsMap.put(fontID, path);
0868:                                        fullPath = file.getCanonicalPath();
0869:                                    } catch (IOException e) {
0870:                                        fullPath = path + File.separator
0871:                                                + fileName;
0872:                                    }
0873:                                    Vector xVal = (Vector) xlfdMap
0874:                                            .get(fullPath);
0875:                                    if (debugFonts) {
0876:                                        logger.info("fullPath=" + fullPath
0877:                                                + " xVal=" + xVal);
0878:                                    }
0879:                                    if ((xVal == null || !xVal
0880:                                            .contains(fontPart))
0881:                                            && (sVal == null)
0882:                                            || !sVal.startsWith("/")) {
0883:                                        if (debugFonts) {
0884:                                            logger.info("Map fontID:" + fontID
0885:                                                    + "to file:" + fullPath);
0886:                                        }
0887:                                        fontNameMap.put(fontID, fullPath);
0888:                                        if (xVal == null) {
0889:                                            xVal = new Vector();
0890:                                            xlfdMap.put(fullPath, xVal);
0891:                                        }
0892:                                        xVal.add(fontPart);
0893:                                    }
0894:
0895:                                    ttype = st.nextToken();
0896:                                    if (ttype != StreamTokenizer.TT_EOL) {
0897:                                        break;
0898:                                    }
0899:                                }
0900:                            }
0901:                        }
0902:                        fr.close();
0903:                    }
0904:                } catch (IOException ioe1) {
0905:                } finally {
0906:                    if (fr != null) {
0907:                        try {
0908:                            fr.close();
0909:                        } catch (IOException ioe2) {
0910:                        }
0911:                    }
0912:                }
0913:            }
0914:
0915:            @Override
0916:            public void loadFonts() {
0917:                super .loadFonts();
0918:                /* These maps are greatly expanded during a loadFonts but
0919:                 * can be reset to their initial state afterwards.
0920:                 * Since preferLocaleFonts() and preferProportionalFonts() will
0921:                 * trigger a partial repopulating from the FontConfiguration
0922:                 * it has to be the inital (empty) state for the latter two, not
0923:                 * simply nulling out.
0924:                 * xFontDirsMap is a special case in that the implementation
0925:                 * will typically not ever need to initialise it so it can be null.
0926:                 */
0927:                xFontDirsMap = null;
0928:                xlfdMap = new HashMap(1);
0929:                fontNameMap = new HashMap(1);
0930:            }
0931:
0932:            // Implements SunGraphicsEnvironment.createFontConfiguration.
0933:            protected FontConfiguration createFontConfiguration() {
0934:                return new MFontConfiguration(this );
0935:            }
0936:
0937:            public FontConfiguration createFontConfiguration(
0938:                    boolean preferLocaleFonts, boolean preferPropFonts) {
0939:
0940:                return new MFontConfiguration(this , preferLocaleFonts,
0941:                        preferPropFonts);
0942:            }
0943:
0944:            /**
0945:             * Returns face name for default font, or null if
0946:             * no face names are used for CompositeFontDescriptors
0947:             * for this platform.
0948:             */
0949:            public String getDefaultFontFaceName() {
0950:                return null;
0951:            }
0952:
0953:            private static native boolean pRunningXinerama();
0954:
0955:            private static native Point getXineramaCenterPoint();
0956:
0957:            /** 
0958:             * Override for Xinerama case: call new Solaris API for getting the correct
0959:             * centering point from the windowing system.
0960:             */
0961:            public Point getCenterPoint() {
0962:                if (runningXinerama()) {
0963:                    Point p = getXineramaCenterPoint();
0964:                    if (p != null) {
0965:                        return p;
0966:                    }
0967:                }
0968:                return super .getCenterPoint();
0969:            }
0970:
0971:            /**
0972:             * Override for Xinerama case
0973:             */
0974:            public Rectangle getMaximumWindowBounds() {
0975:                if (runningXinerama()) {
0976:                    return getXineramaWindowBounds();
0977:                } else {
0978:                    return super .getMaximumWindowBounds();
0979:                }
0980:            }
0981:
0982:            public boolean runningXinerama() {
0983:                if (xinerState == null) {
0984:                    // pRunningXinerama() simply returns a global boolean variable,
0985:                    // so there is no need to synchronize here
0986:                    xinerState = Boolean.valueOf(pRunningXinerama());
0987:                }
0988:                return xinerState.booleanValue();
0989:            }
0990:
0991:            /**
0992:             * Return the bounds for a centered Window on a system running in Xinerama
0993:             * mode.
0994:             *
0995:             * Calculations are based on the assumption of a perfectly rectangular
0996:             * display area (display edges line up with one another, and displays
0997:             * have consistent width and/or height).
0998:             *
0999:             * The bounds to return depend on the arrangement of displays and on where
1000:             * Windows are to be centered.  There are two common situations:
1001:             *
1002:             * 1) The center point lies at the center of the combined area of all the
1003:             *    displays.  In this case, the combined area of all displays is
1004:             *    returned.
1005:             *
1006:             * 2) The center point lies at the center of a single display.  In this case
1007:             *    the user most likely wants centered Windows to be constrained to that
1008:             *    single display.  The boundaries of the one display are returned.
1009:             *
1010:             * It is possible for the center point to be at both the center of the
1011:             * entire display space AND at the center of a single monitor (a square of
1012:             * 9 monitors, for instance).  In this case, the entire display area is
1013:             * returned.
1014:             *
1015:             * Because the center point is arbitrarily settable by the user, it could
1016:             * fit neither of the cases above.  The fallback case is to simply return
1017:             * the combined area for all screens.
1018:             */
1019:            protected Rectangle getXineramaWindowBounds() {
1020:                Point center = getCenterPoint();
1021:                Rectangle unionRect, tempRect;
1022:                GraphicsDevice[] gds = getScreenDevices();
1023:                Rectangle centerMonitorRect = null;
1024:                int i;
1025:
1026:                // if center point is at the center of all monitors
1027:                // return union of all bounds
1028:                //
1029:                //  MM*MM     MMM       M
1030:                //            M*M       *
1031:                //            MMM       M
1032:
1033:                // if center point is at center of a single monitor (but not of all
1034:                // monitors)
1035:                // return bounds of single monitor
1036:                //
1037:                // MMM         MM
1038:                // MM*         *M
1039:
1040:                // else, center is in some strange spot (such as on the border between
1041:                // monitors), and we should just return the union of all monitors
1042:                //
1043:                // MM          MMM
1044:                // MM          MMM
1045:
1046:                unionRect = getUsableBounds(gds[0]);
1047:
1048:                for (i = 0; i < gds.length; i++) {
1049:                    tempRect = getUsableBounds(gds[i]);
1050:                    if (centerMonitorRect == null
1051:                            &&
1052:                            // add a pixel or two for fudge-factor
1053:                            (tempRect.width / 2) + tempRect.x > center.x - 1
1054:                            && (tempRect.height / 2) + tempRect.y > center.y - 1
1055:                            && (tempRect.width / 2) + tempRect.x < center.x + 1
1056:                            && (tempRect.height / 2) + tempRect.y < center.y + 1) {
1057:                        centerMonitorRect = tempRect;
1058:                    }
1059:                    unionRect = unionRect.union(tempRect);
1060:                }
1061:
1062:                // first: check for center of all monitors (video wall)
1063:                // add a pixel or two for fudge-factor
1064:                if ((unionRect.width / 2) + unionRect.x > center.x - 1
1065:                        && (unionRect.height / 2) + unionRect.y > center.y - 1
1066:                        && (unionRect.width / 2) + unionRect.x < center.x + 1
1067:                        && (unionRect.height / 2) + unionRect.y < center.y + 1) {
1068:
1069:                    if (dbg.on) {
1070:                        dbg
1071:                                .println("Video Wall: center point is at center of all displays.");
1072:                    }
1073:                    return unionRect;
1074:                }
1075:
1076:                // next, check if at center of one monitor
1077:                if (centerMonitorRect != null) {
1078:                    if (dbg.on) {
1079:                        dbg
1080:                                .println("Center point at center of a particular monitor, but not of the entire virtual display.");
1081:                    }
1082:                    return centerMonitorRect;
1083:                }
1084:
1085:                // otherwise, the center is at some weird spot: return unionRect
1086:                if (dbg.on) {
1087:                    dbg
1088:                            .println("Center point is somewhere strange - return union of all bounds.");
1089:                }
1090:                return unionRect;
1091:            }
1092:
1093:            /**
1094:             * From the DisplayChangedListener interface; devices do not need
1095:             * to react to this event.
1096:             */
1097:            @Override
1098:            public void paletteChanged() {
1099:            }
1100:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.