Showing the changes to java/pkg/awt/iFontPeer.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,276 @@ | ||
| 1 | +/* | |
| 2 | + * %W% - %E% | |
| 3 | + */ | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Inferno's Font peer | |
| 7 | + * | |
| 8 | + */ | |
| 9 | + | |
| 10 | + /* | |
| 11 | + * If you're not using xemacs to view this file, you may find it's indentation | |
| 12 | + * more ledgible if you set your tabstops to four spaces. | |
| 13 | + */ | |
| 14 | +package inferno.awt; | |
| 15 | + | |
| 16 | +import java.io.FileNotFoundException; | |
| 17 | +import java.awt.Font; | |
| 18 | +import java.util.Properties; | |
| 19 | +import java.util.Hashtable; | |
| 20 | +import java.util.Vector; | |
| 21 | +import java.io.File; | |
| 22 | +import java.io.InputStream; | |
| 23 | +import java.io.FileInputStream; | |
| 24 | +import java.io.BufferedInputStream; | |
| 25 | +import java.util.StringTokenizer; | |
| 26 | + | |
| 27 | +public class iFontPeer implements java.awt.peer.FontPeer { | |
| 28 | + | |
| 29 | + // a default Inferno pathname to a font | |
| 30 | + // "/fonts/lucidasans/latin1.7.font" is a popular default font | |
| 31 | + private final static String defifpathname = "*default*"; | |
| 32 | + | |
| 33 | + /* | |
| 34 | + An object to hold a Limbo reference of type ref Draw->Font | |
| 35 | + the handle to Inferno platform font capabilities. | |
| 36 | + Inferno JNI access as this.iFontRef. | |
| 37 | + Pertinent size metrics are kept here in the peer for quicker | |
| 38 | + text rendering. | |
| 39 | + */ | |
| 40 | + Object iFontRef; | |
| 41 | + int iAscent = -1; // Inferno font's ascent value | |
| 42 | + int iHeight = -1; // Inferno font's height value | |
| 43 | + int fLeading = -1; // a fudged value for leading (none in Inferno fonts) | |
| 44 | + String iName = ""; // Inferno font's name (should match ifpathname) | |
| 45 | + | |
| 46 | + private static Properties fprops; | |
| 47 | + static { | |
| 48 | + // Find property file | |
| 49 | + String jhome = System.getProperty("java.home"); | |
| 50 | + if (jhome == null){ | |
| 51 | + throw new Error("java.home property not set"); | |
| 52 | + } | |
| 53 | + // trace("jhome=" + jhome); | |
| 54 | + | |
| 55 | + String language = System.getProperty("user.language", "en"); | |
| 56 | + String region = System.getProperty("user.region"); | |
| 57 | + | |
| 58 | + // trace("language=" + language); | |
| 59 | + // trace("region=" + region); | |
| 60 | + // trace("File.separator=" + File.separator); | |
| 61 | + | |
| 62 | + try { | |
| 63 | + File f = null; | |
| 64 | + if (region != null) { | |
| 65 | + f = new File(jhome + File.separator + | |
| 66 | + "lib" + File.separator + | |
| 67 | + "font.properties." + language + "_" + | |
| 68 | + region); | |
| 69 | + } | |
| 70 | + | |
| 71 | + if (f == null || !f.canRead()) { | |
| 72 | + f = new File(jhome + File.separator + | |
| 73 | + "lib" + File.separator + "font.properties." + | |
| 74 | + language); | |
| 75 | + if (!f.canRead()) { | |
| 76 | + f = new File(jhome + File.separator + | |
| 77 | + "lib" + File.separator + "font.properties"); | |
| 78 | + if (!f.canRead()){ | |
| 79 | + throw new Exception(); | |
| 80 | + } | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + fprops = new Properties(); | |
| 85 | + | |
| 86 | + // Load property file | |
| 87 | + // trace("trying to load props at path " + f.getPath()); | |
| 88 | + InputStream in = | |
| 89 | + new BufferedInputStream(new FileInputStream(f.getPath())); | |
| 90 | + fprops.load(in); | |
| 91 | + in.close(); | |
| 92 | + } catch (Exception e){ | |
| 93 | + System.out.println("iFontPeer: can't load font.properties"); | |
| 94 | + System.out.println("exception: " + e.getMessage()); | |
| 95 | + e.printStackTrace(); | |
| 96 | + } // end try | |
| 97 | + } // end static | |
| 98 | + | |
| 99 | + | |
| 100 | + // The do-nothing constructor | |
| 101 | + public iFontPeer(String name, int style) { | |
| 102 | + // Don't do anything with name and style, they're implementation | |
| 103 | + // artifacts from a different (better?) world of scalable | |
| 104 | + // platform fonts where size is a final argument to platform | |
| 105 | + // dependant rendering libraries, but Inferno's are static bitmaps. | |
| 106 | + // | |
| 107 | + // a better (more general) signatures for this constructor would | |
| 108 | + // have been FontPeer(Font font) or | |
| 109 | + // FontPeer(String name,int style,int size) | |
| 110 | + // but alas, Sun's API hasn't been quite general enough in that regard. | |
| 111 | + } | |
| 112 | + | |
| 113 | + // Native method to actually create font in Inferno Display and | |
| 114 | + // populate this object with reference to Draw->Font and some | |
| 115 | + // font metrics. | |
| 116 | + private native void initFontPeer(String ifpathname) throws FileNotFoundException; | |
| 117 | + | |
| 118 | + // | |
| 119 | + // initializeFontPeer is called by java.awt.Font.java so this | |
| 120 | + // method must, regretably, have public scope. | |
| 121 | + // | |
| 122 | + public String initializeFontPeer(String name, int style, int size) | |
| 123 | + { | |
| 124 | + String ifpn = ""; // pathname to Inferno font | |
| 125 | + // trace("iFontPeer.initializeFontPeer(): name=" + name +" ,style=" | |
| 126 | + // + style + ", size=" + size); | |
| 127 | + | |
| 128 | + boolean triedDefault = false; | |
| 129 | + ifpn = mapifpath(name, style, size); | |
| 130 | + if (ifpn == null) { | |
| 131 | + ifpn = defifpathname; | |
| 132 | + } | |
| 133 | + | |
| 134 | + retry: | |
| 135 | + try { | |
| 136 | + initFontPeer(ifpn); // sets iName, iAscent, iHeight, and fLeading | |
| 137 | + } catch (FileNotFoundException e) { | |
| 138 | + // case: properties maps to a file but font file doesn't | |
| 139 | + // exist | |
| 140 | + if (!triedDefault) { | |
| 141 | + triedDefault = true; | |
| 142 | + ifpn = defifpathname; | |
| 143 | + // trace("initializeFontPeer: trying default"); | |
| 144 | + break retry; | |
| 145 | + } | |
| 146 | + } | |
| 147 | + | |
| 148 | + if (debug) { | |
| 149 | + trace("iFontPeer.initializeFontPeer():"); | |
| 150 | + trace(" iName=" + iName); | |
| 151 | + trace(" iAscent=" + iAscent + " iHeight=" + iHeight); | |
| 152 | + } | |
| 153 | + return ifpn; | |
| 154 | + } | |
| 155 | + | |
| 156 | + // | |
| 157 | + // map a Java font triple into the full pathname of an Inferno | |
| 158 | + // font description file. | |
| 159 | + // | |
| 160 | + private static String mapifpath(String name, int style, int size) { | |
| 161 | + | |
| 162 | + if (fprops == null) { | |
| 163 | + return defifpathname; | |
| 164 | + } | |
| 165 | + | |
| 166 | + String aName = name.toLowerCase(); | |
| 167 | + String aStyle = styleStr(style); | |
| 168 | + String aSize = String.valueOf(size); | |
| 169 | + | |
| 170 | + //trace("mapifpath(" + aName + ", " + aStyle + ", " + aSize + ")"); | |
| 171 | + String aStr = aName + "." + aStyle + "." + aSize; | |
| 172 | + int idx; | |
| 173 | + | |
| 174 | + // perform face name substitution | |
| 175 | + String rStr = fprops.getProperty("alias." + aName); | |
| 176 | + if (rStr != null && rStr.indexOf('.') < 0) { | |
| 177 | + aName = rStr; | |
| 178 | + } | |
| 179 | + //trace("gp1 rStr=" +rStr+ " aName=" +aName+ " aStyle=" +aStyle+ | |
| 180 | + // " aSize=" + aSize); | |
| 181 | + | |
| 182 | + // perform style substitution on result of above | |
| 183 | + rStr = fprops.getProperty("alias." + aName + "." + aStyle); | |
| 184 | + if (rStr != null) { | |
| 185 | + idx = rStr.indexOf('.'); | |
| 186 | + if (idx > 0 && rStr.lastIndexOf('.') == idx && | |
| 187 | + (idx+1 < rStr.length())) | |
| 188 | + { | |
| 189 | + aName = rStr.substring(0,idx); | |
| 190 | + aStyle = rStr.substring(idx+1); | |
| 191 | + } | |
| 192 | + } | |
| 193 | + //trace("gp2 rStr=" +rStr+ " aName=" +aName+ " aStyle=" +aStyle+ | |
| 194 | + // " aSize=" + aSize); | |
| 195 | + | |
| 196 | + | |
| 197 | + // Now see if there's a complete alias for this "font+style+size" | |
| 198 | + rStr = fprops.getProperty("alias." + aName + "." + aStyle + | |
| 199 | + "." + aSize); | |
| 200 | + if (rStr != null) { | |
| 201 | + StringTokenizer st = new StringTokenizer(rStr,".",false); | |
| 202 | + if (st.countTokens() == 3) { | |
| 203 | + aName = st.nextToken(); | |
| 204 | + aStyle = st.nextToken(); | |
| 205 | + aSize = st.nextToken(); | |
| 206 | + } | |
| 207 | + } | |
| 208 | + //trace("gp3 rStr=" +rStr+ " aName=" +aName+ " aStyle=" +aStyle+ | |
| 209 | + // " aSize=" + aSize); | |
| 210 | + | |
| 211 | + | |
| 212 | + // after these substitutions, see if the font string has | |
| 213 | + // a match, applying the followin heuristic. | |
| 214 | + // if stlye isn't "plain", adjust size +-2, if no match | |
| 215 | + // change style to "plain" and proceed per style is "plain" | |
| 216 | + // if style is "plain" adjust size +-4 if need be. | |
| 217 | + // | |
| 218 | + | |
| 219 | + while(true) { | |
| 220 | + int nsize; | |
| 221 | + boolean up = true; | |
| 222 | + int range = (style != Font.PLAIN) ? 2 : 4; | |
| 223 | + | |
| 224 | + for (int i = 0; i <= range;) { | |
| 225 | + nsize = Math.abs(size + ((up) ? i : -i)); | |
| 226 | + // trace("nsize=" + nsize); | |
| 227 | + aSize = String.valueOf(nsize); | |
| 228 | + rStr = fprops.getProperty(aName +"."+ aStyle + "." + aSize); | |
| 229 | + if (rStr != null) { | |
| 230 | + //trace("***mapifpath: got it!"); | |
| 231 | + break; | |
| 232 | + } | |
| 233 | + if (!up) { | |
| 234 | + i++; | |
| 235 | + } | |
| 236 | + up = (!up); | |
| 237 | + } | |
| 238 | + if (rStr == null) { | |
| 239 | + if (style != Font.PLAIN) { // retry with plain style | |
| 240 | + style = Font.PLAIN; | |
| 241 | + aStyle = styleStr(style); | |
| 242 | + //trace("***mapifpath: retry w/plain font!, nsize=" + nsize); | |
| 243 | + continue; | |
| 244 | + } | |
| 245 | + rStr = defifpathname; // no Match, returns default | |
| 246 | + } | |
| 247 | + break; | |
| 248 | + } | |
| 249 | + trace ("mapifpath: gp4 aName=" +aName+ " aStyle=" +aStyle+ | |
| 250 | + " aSize=" + aSize + " rStr=" + rStr); | |
| 251 | + return(rStr); | |
| 252 | + } | |
| 253 | + | |
| 254 | + /* | |
| 255 | + * return String representation of style | |
| 256 | + */ | |
| 257 | + private static String styleStr(int num){ | |
| 258 | + switch(num){ | |
| 259 | + case Font.BOLD: | |
| 260 | + return "bold"; | |
| 261 | + case Font.ITALIC: | |
| 262 | + return "italic"; | |
| 263 | + case Font.ITALIC+Font.BOLD: | |
| 264 | + return "bolditalic"; | |
| 265 | + default: | |
| 266 | + return "plain"; | |
| 267 | + } | |
| 268 | + } | |
| 269 | + | |
| 270 | + private static final boolean debug = false; | |
| 271 | + private static void trace(String arg) { | |
| 272 | + if (debug) { | |
| 273 | + System.out.println(arg); | |
| 274 | + } | |
| 275 | + } | |
| 276 | +} | |