001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package org.jvnet.substance.fonts;
031:
032: import java.awt.*;
033: import java.awt.geom.AffineTransform;
034: import java.lang.reflect.Method;
035: import java.util.StringTokenizer;
036:
037: import javax.swing.UIDefaults;
038: import javax.swing.plaf.FontUIResource;
039:
040: /**
041: * The default font policy for Gnome desktops.
042: *
043: * @author Kirill Grouchnikov
044: */
045: public class DefaultGnomeFontPolicy implements FontPolicy {
046: /**
047: * Font scale.
048: */
049: private static double fontScale;
050:
051: static {
052: GraphicsEnvironment ge = GraphicsEnvironment
053: .getLocalGraphicsEnvironment();
054: GraphicsConfiguration gc = ge.getDefaultScreenDevice()
055: .getDefaultConfiguration();
056: AffineTransform at = gc.getNormalizingTransform();
057: fontScale = at.getScaleY();
058: }
059:
060: /*
061: * (non-Javadoc)
062: *
063: * @see org.jvnet.substance.fonts.FontPolicy#getFontSet(java.lang.String,
064: * javax.swing.UIDefaults)
065: */
066: public FontSet getFontSet(String lafName, UIDefaults table) {
067: Object defaultGtkFontName = Toolkit.getDefaultToolkit()
068: .getDesktopProperty("gnome.Gtk/FontName");
069: String family = "";
070: int style = Font.PLAIN;
071: int size = 10;
072: if (defaultGtkFontName instanceof String) {
073: String pangoName = (String) defaultGtkFontName;
074: StringTokenizer tok = new StringTokenizer(pangoName);
075: while (tok.hasMoreTokens()) {
076: String word = tok.nextToken();
077: boolean allDigits = true;
078: for (int i = 0; i < word.length(); i++) {
079: if (!Character.isDigit(word.charAt(i))) {
080: allDigits = false;
081: break;
082: }
083: }
084:
085: if (word.equalsIgnoreCase("italic")) {
086: style |= Font.ITALIC;
087: } else if (word.equalsIgnoreCase("bold")) {
088: style |= Font.BOLD;
089: } else if (allDigits) {
090: try {
091: size = Integer.parseInt(word);
092: } catch (NumberFormatException nfe) {
093: size = 10;
094: }
095: } else {
096: if (family.length() > 0) {
097: family += " ";
098: }
099: family += word;
100: }
101: }
102: }
103:
104: double dsize = size * getPointsToPixelsRatio();
105:
106: size = (int) (dsize + 0.5);
107: if (size < 1) {
108: size = 1;
109: }
110:
111: if (family.length() == 0)
112: family = "sans";
113: // Font controlFont = new Font(family, style, size);
114:
115: Font controlFont = null;
116: // make some black magic with sun-private classes
117: // to better map the logical font name (such as sans)
118: // to an actual font (such as DejaVu Sans).
119: String fcFamilyLC = family.toLowerCase();
120: try {
121: Class fontManagerClass = Class
122: .forName("sun.font.FontManager");
123: Method mapFcMethod = fontManagerClass.getMethod(
124: "mapFcName", new Class[] { String.class });
125: Object mapFcMethodResult = mapFcMethod.invoke(null,
126: fcFamilyLC);
127: if (mapFcMethodResult != null) {
128: Method getFontConfigFUIRMethod = fontManagerClass
129: .getMethod("getFontConfigFUIR", new Class[] {
130: String.class, int.class, int.class });
131: controlFont = (Font) getFontConfigFUIRMethod.invoke(
132: null, fcFamilyLC, style, size);
133: } else {
134: Font font = new FontUIResource(family, style, size);
135: Method getCompositeFontUIResourceMethod = fontManagerClass
136: .getMethod("getCompositeFontUIResource",
137: new Class[] { Font.class });
138: controlFont = (Font) getCompositeFontUIResourceMethod
139: .invoke(null, font);
140: }
141: } catch (Throwable t) {
142: controlFont = new Font(family, style, size);
143: }
144:
145: return FontSets.createDefaultFontSet(controlFont);
146: }
147:
148: public static double getPointsToPixelsRatio() {
149: // for details behind the computations, look in
150: // com.sun.java.swing.plaf.gtk.PangoFonts
151: int dpi = 96;
152: Object value = Toolkit.getDefaultToolkit().getDesktopProperty(
153: "gnome.Xft/DPI");
154: if (value instanceof Integer) {
155: dpi = ((Integer) value).intValue() / 1024;
156: if (dpi == -1) {
157: dpi = 96;
158: }
159: if (dpi < 50) {
160: dpi = 50;
161: }
162: return dpi / 72.0;
163: } else {
164: return fontScale;
165: }
166: }
167: }
|