KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > java > swing > plaf > gtk > PangoFonts


1 /*
2  * @(#)PangoFonts.java 1.11 04/03/31
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.java.swing.plaf.gtk;
9
10 import java.awt.*;
11 import java.awt.geom.AffineTransform JavaDoc;
12 import javax.swing.plaf.FontUIResource JavaDoc;
13 import java.util.StringTokenizer JavaDoc;
14 import sun.font.FontManager;
15
16 /**
17  * @author Shannon Hickey
18  * @author Leif Samuelsson
19  * @version 1.11 03/31/04
20  */

21 class PangoFonts {
22
23     // A simple array for now, but this could be a HashMap if
24
// many more mappings are added
25
private static final String JavaDoc[][] nameMap = {{"sans", "sansserif"},
26                                                {"monospace", "monospaced"}};
27
28     /**
29      * Calculate a default scale factor for fonts in this L&F to match
30      * the reported resolution of the screen.
31      * Java 2D specified a default user-space scale of 72dpi.
32      * This is unlikely to correspond to that of the real screen.
33      * The Xserver reports a value which may be used to adjust for this.
34      * and Java 2D exposes it via a normalizing transform.
35      * However many Xservers report a hard-coded 90dpi whilst others report a
36      * calculated value based on possibly incorrect data.
37      * That is something that must be solved at the X11 level
38      * Note that in an X11 multi-screen environment, the default screen
39      * is the one used by the JRE so it is safe to use it here.
40      */

41     private static double fontScale;
42
43     static {
44         GraphicsEnvironment ge =
45            GraphicsEnvironment.getLocalGraphicsEnvironment();
46         GraphicsConfiguration gc =
47             ge.getDefaultScreenDevice().getDefaultConfiguration();
48         AffineTransform JavaDoc at = gc.getNormalizingTransform();
49         fontScale = at.getScaleY();
50     }
51     
52     private static String JavaDoc mapName(String JavaDoc name) {
53         for (int i = 0; i < nameMap.length; i++) {
54             if (name.equals(nameMap[i][0])) {
55                 return nameMap[i][1];
56             }
57         }
58         
59         return null;
60     }
61
62     /**
63      * Parses a String containing a pango font description and returns
64      * a Font object.
65      *
66      * @param pangoName a String describing a pango font
67      * e.g. "Sans Italic 10"
68      * @return a Font object as a FontUIResource
69      * or null if no suitable font could be created.
70      */

71     static Font lookupFont(String JavaDoc pangoName) {
72         String JavaDoc family = "";
73         int style = Font.PLAIN;
74         int size = 10;
75
76         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(pangoName);
77
78         while (tok.hasMoreTokens()) {
79             String JavaDoc word = tok.nextToken();
80
81             if (word.equalsIgnoreCase("italic")) {
82                 style |= Font.ITALIC;
83             } else if (word.equalsIgnoreCase("bold")) {
84                 style |= Font.BOLD;
85             } else if (GTKScanner.CHARS_DIGITS.indexOf(word.charAt(0)) != -1) {
86                 try {
87                     size = Integer.parseInt(word);
88                 } catch (NumberFormatException JavaDoc ex) {
89                 }
90             } else {
91                 if (family.length() > 0) {
92                     family += " ";
93                 }
94                 
95                 family += word;
96             }
97         }
98
99     /*
100      * Java 2D font point sizes are in a user-space scale of 72dpi.
101      * GTK allows a user to configure a "dpi" property used to scale
102      * the fonts used to match a user's preference.
103      * To match the font size of GTK apps we need to obtain this DPI and
104      * adjust as follows:
105      * Some versions of GTK use XSETTINGS if available to dynamically
106      * monitor user-initiated changes in the DPI to be used by GTK
107      * apps. This value is also made available as the Xft.dpi X resource.
108      * This is presumably a function of the font preferences API and/or
109      * the manner in which it requests the toolkit to update the default
110      * for the desktop. This dual approach is probably necessary since
111      * other versions of GTK - or perhaps some apps - determine the size
112      * to use only at start-up from that X resource.
113      * If that resource is not set then GTK scales for the DPI resolution
114      * reported by the Xserver using the formula
115      * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) * 25.4
116      * (25.4mm == 1 inch).
117      * JDK tracks the Xft.dpi XSETTINGS property directly so it can
118      * dynamically change font size by tracking just that value.
119      * If that resource is not available use the same fall back formula
120      * as GTK (see calculation for fontScale).
121          *
122      * GTK's default setting for Xft.dpi is 96 dpi (and it seems -1
123      * apparently also can mean that "default"). However this default
124      * isn't used if there's no property set. The real default in the
125      * absence of a resource is the Xserver reported dpi.
126      * Finally this DPI is used to calculate the nearest Java 2D font
127      * 72 dpi font size.
128      * There are cases in which JDK behaviour may not exactly mimic
129      * GTK native app behaviour :
130      * 1) When a GTK app is not able to dynamically track the changes
131      * (does not use XSETTINGS), JDK will resize but other apps will
132      * not. This is OK as JDK is exhibiting preferred behaviour and
133      * this is probably how all later GTK apps will behave
134          * 2) When a GTK app does not use XSETTINGS and for some reason
135      * the XRDB property is not present. JDK will pick up XSETTINGS
136      * and the GTK app will use the Xserver default. Since its
137      * impossible for JDK to know that some other GTK app is not
138      * using XSETTINGS its impossible to account for this and in any
139      * case for it to be a problem the values would have to be different.
140      * It also seems unlikely to arise except when a user explicitly
141      * deletes the X resource database entry.
142          * 3) Because of rounding errors sizes may differ very slightly
143      * between JDK and GTK. To fix that would at the very least require
144          * Swing to specify floating pt font sizes.
145      * Eg "10 pts" for GTK at 96 dpi to get the same size at Java 2D's
146      * 72 dpi you'd need to specify exactly 13.33.
147      * There also some other issues to be aware of for the future:
148      * GTK specifies the Xft.dpi value as server-wide which when used
149      * on systems with 2 distinct X screens with different physical DPI
150      * the font sizes will inevitably appear different. It would have
151      * been a more user-friendly design to further adjust that one
152      * setting depending on the screen resolution to achieve perceived
153      * equivalent sizes. If such a change were ever to be made in GTK
154      * we would need to update for that.
155      */

156     double dsize = size;
157         int dpi = 96;
158         Object JavaDoc value =
159             Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI");
160         if (value instanceof Integer JavaDoc) {
161             dpi = ((Integer JavaDoc)value).intValue() / 1024;
162         if (dpi == -1) {
163           dpi = 96;
164         }
165         if (dpi < 50) { /* 50 dpi is the minimum value gnome allows */
166         dpi = 50;
167         }
168         /* The Java rasteriser assumes pts are in a user space of
169          * 72 dpi, so we need to adjust for that.
170          */

171         dsize = ((double)(dpi * size)/ 72.0);
172         } else {
173         /* If there's no property, GTK scales for the resolution
174          * reported by the Xserver using the formula listed above.
175          * fontScale already accounts for the 72 dpi Java 2D space.
176          */

177         dsize = size * fontScale;
178     }
179
180     /* Round size to nearest integer pt size */
181         size = (int)(dsize + 0.5);
182     if (size < 1) {
183         size = 1;
184     }
185
186         String JavaDoc mappedName = mapName(family.toLowerCase());
187         if (mappedName != null) {
188             family = mappedName;
189         }
190
191         Font font = new FontUIResource JavaDoc(family, style, size);
192         if (!FontManager.fontSupportsDefaultEncoding(font)) {
193             font = FontManager.getCompositeFontUIResource(font);
194         }
195         return font;
196     }
197 }
198
199
Popular Tags