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 | } | ||