Showing the changes to java/pkg/awt/iFontMetrics.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,266 @@ | |||
| 1 | /* | ||
| 2 | * %W% - %E% | ||
| 3 | */ | ||
| 4 | |||
| 5 | /* | ||
| 6 | The only font metrics that Inferno provides are height, the distance | ||
| 7 | in pixels between baselines of lines of text rendered in a particular | ||
| 8 | font, and ascent, the distance from the top of the bounding box to the | ||
| 9 | baseline. So there really isn't much vertical information to provide. | ||
| 10 | In particular there's no leading, and descent information. | ||
| 11 | |||
| 12 | To do better than this will require, putting max bounds, leading, and | ||
| 13 | descent information in the Inferno subfont files, and augmenting $Draw | ||
| 14 | built-in module to make this information visible to Limbo programs. | ||
| 15 | */ | ||
| 16 | |||
| 17 | /* | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | package inferno.awt; | ||
| 22 | |||
| 23 | import java.awt.*; | ||
| 24 | import java.util.Hashtable; | ||
| 25 | import java.lang.IllegalArgumentException; | ||
| 26 | |||
| 27 | /** | ||
| 28 | * A font metrics object for a font. | ||
| 29 | * | ||
| 30 | */ | ||
| 31 | public class iFontMetrics extends FontMetrics { | ||
| 32 | |||
| 33 | private static final boolean debug = false; | ||
| 34 | |||
| 35 | int widths[]; | ||
| 36 | int ascent; | ||
| 37 | int descent; | ||
| 38 | int leading; | ||
| 39 | int height; | ||
| 40 | int maxAscent; | ||
| 41 | int maxDescent; | ||
| 42 | int maxHeight; | ||
| 43 | |||
| 44 | /* | ||
| 45 | maxAdvance can't be readily determined without | ||
| 46 | parsing the Inferno font file and calling | ||
| 47 | Draw->(Draw->Font).width() for every char mapped by | ||
| 48 | that Inferno Font. An alternate fudging strategy is to | ||
| 49 | set it to the max width of any char in the first 256 | ||
| 50 | (getWidths()) characters. | ||
| 51 | */ | ||
| 52 | int maxAdvance = -1; | ||
| 53 | |||
| 54 | private boolean needWidths = true; | ||
| 55 | |||
| 56 | // rather than ask our Font for it's peer everytime we want it. We'll | ||
| 57 | // ask once at construction time, as a small optimization. | ||
| 58 | |||
| 59 | private iFontPeer ifontpeer; | ||
| 60 | |||
| 61 | public iFontMetrics(Font font) { | ||
| 62 | super(font); | ||
| 63 | // Some vertical font metrics (height, and ascent) are (conveniently) | ||
| 64 | // already available in the iFontPeer of a constructed Font. | ||
| 65 | if (font == null) { | ||
| 66 | throw new IllegalArgumentException("font"); | ||
| 67 | } | ||
| 68 | ifontpeer = (iFontPeer)font.getPeer(); // our Inferno peer | ||
| 69 | height = ifontpeer.iHeight; | ||
| 70 | ascent = ifontpeer.iAscent; | ||
| 71 | |||
| 72 | // fudge a pixel for leading if the difference between height | ||
| 73 | // and ascent permits, done by iFontPeer() like so | ||
| 74 | // leading = ((height - ascent) > 2) ? 1 : 0; | ||
| 75 | leading = ifontpeer.fLeading; | ||
| 76 | descent = height - ascent - leading; | ||
| 77 | |||
| 78 | // There's no information regarding the following available to Limbo, | ||
| 79 | // or even in the Inferno subfont files, so fudge 'em. | ||
| 80 | maxHeight = height; | ||
| 81 | maxAscent = ascent; | ||
| 82 | maxDescent = descent; | ||
| 83 | |||
| 84 | // widths and maybe maxAdvance is evaluated lazily as needed. | ||
| 85 | } | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Get leading | ||
| 89 | */ | ||
| 90 | public int getLeading() { | ||
| 91 | return leading; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Get ascent. | ||
| 96 | */ | ||
| 97 | public int getAscent() { | ||
| 98 | return ascent; | ||
| 99 | } | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Get descent | ||
| 103 | */ | ||
| 104 | public int getDescent() { | ||
| 105 | return descent; | ||
| 106 | } | ||
| 107 | |||
| 108 | /** | ||
| 109 | * Get height | ||
| 110 | */ | ||
| 111 | public int getHeight() { | ||
| 112 | return height; | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * Get maxAscent | ||
| 117 | */ | ||
| 118 | public int getMaxAscent() { | ||
| 119 | return maxAscent; | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Get maxDescent | ||
| 124 | */ | ||
| 125 | public int getMaxDescent() { | ||
| 126 | return maxDescent; | ||
| 127 | } | ||
| 128 | |||
| 129 | /** | ||
| 130 | * Get maxAdvance | ||
| 131 | */ | ||
| 132 | public int getMaxAdvance() { | ||
| 133 | if (needWidths) { | ||
| 134 | initWidths(); | ||
| 135 | } | ||
| 136 | return maxAdvance; | ||
| 137 | } | ||
| 138 | |||
| 139 | /** | ||
| 140 | * Returns the advance width of the sprcified character in this Font. | ||
| 141 | */ | ||
| 142 | public int charWidth(char ch) { | ||
| 143 | if (ch < 256) { // chars are zero extended upon promotin to ints | ||
| 144 | if (needWidths) { | ||
| 145 | initWidths(); | ||
| 146 | } | ||
| 147 | return widths[ch & 0xFF]; | ||
| 148 | } else { | ||
| 149 | char data[] = { ch }; | ||
| 150 | return charsWidth(data, 0, 1); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | |||
| 155 | /** | ||
| 156 | * Return the advance widh of the specified chars in this Font | ||
| 157 | */ | ||
| 158 | public int charsWidth(char data[], int off, int len) { | ||
| 159 | int w = 0; | ||
| 160 | int tlen = len; | ||
| 161 | int toff = off; | ||
| 162 | boolean tooBig = false; | ||
| 163 | if (data == null || off < 0) { | ||
| 164 | throw new IllegalArgumentException(); | ||
| 165 | } | ||
| 166 | while(len-- > 0) { | ||
| 167 | if (data[off] >= 256) { | ||
| 168 | tooBig = true; | ||
| 169 | break; | ||
| 170 | } | ||
| 171 | if (needWidths) { | ||
| 172 | initWidths(); | ||
| 173 | } | ||
| 174 | w += widths[data[off++]]; | ||
| 175 | } | ||
| 176 | if (tooBig) { | ||
| 177 | if (debug) { | ||
| 178 | System.out.println("iFontMetrics.charsWidth - tooBig"); | ||
| 179 | } | ||
| 180 | w = stringWidth(new String(data, off, len)); | ||
| 181 | } | ||
| 182 | return w; | ||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | /** | ||
| 187 | * Return the width of the specified string in this Font. | ||
| 188 | * | ||
| 189 | * Why not bust up the string into a char[] and try for the optimization | ||
| 190 | * of charsWidth if all elemment values are less than 256? -jfs? | ||
| 191 | */ | ||
| 192 | public int stringWidth(String str) { | ||
| 193 | if (str == null) { | ||
| 194 | throw new IllegalArgumentException(); | ||
| 195 | } | ||
| 196 | return iStringWidth(str); | ||
| 197 | } | ||
| 198 | |||
| 199 | public int bytesWidth(byte[] data, int off, int len) { | ||
| 200 | // check args here? | ||
| 201 | if (data == null || off < 0 || len < 0) { | ||
| 202 | throw new IllegalArgumentException(); | ||
| 203 | } | ||
| 204 | byte[] ndata = new byte[len]; | ||
| 205 | System.arraycopy(data, off, ndata, 0, len); | ||
| 206 | return iBytesWidth(ndata); | ||
| 207 | } | ||
| 208 | |||
| 209 | // Compute width of string in this font. | ||
| 210 | private native int iStringWidth(String str); | ||
| 211 | |||
| 212 | // translate bytes from UTF-8 encoding into a Unicode Limbo string, | ||
| 213 | // compute the advance width of the string in this Font and return | ||
| 214 | // the advance in pixels. | ||
| 215 | private native int iBytesWidth(byte data[]); | ||
| 216 | |||
| 217 | // get advance widths of the first 256 characters of this font. | ||
| 218 | private synchronized void initWidths() { | ||
| 219 | widths = new int[256]; | ||
| 220 | maxAdvance = iInitWidths(widths); | ||
| 221 | if (debug) { | ||
| 222 | System.out.println("iFontMetrics.initWidths(): maxAdvance=" + maxAdvance); | ||
| 223 | } | ||
| 224 | needWidths = false; | ||
| 225 | } | ||
| 226 | |||
| 227 | // populates widths with the advance width of the first 256 chars | ||
| 228 | // in this font, returns the width of the widest character. | ||
| 229 | private native int iInitWidths(int widths[]); | ||
| 230 | |||
| 231 | /** | ||
| 232 | * Get the widths of the first 256 characters in the font. | ||
| 233 | */ | ||
| 234 | public int[] getWidths() { | ||
| 235 | if (needWidths) { | ||
| 236 | initWidths(); | ||
| 237 | } | ||
| 238 | return widths; | ||
| 239 | } | ||
| 240 | |||
| 241 | static Hashtable table = new Hashtable(); | ||
| 242 | |||
| 243 | static synchronized FontMetrics getFontMetrics(Font font) { | ||
| 244 | if (font == null) { | ||
| 245 | throw new NullPointerException("FontMetrics.getFontMetrics()"); | ||
| 246 | } | ||
| 247 | FontMetrics fm = (FontMetrics)table.get(font); | ||
| 248 | if (fm == null) { | ||
| 249 | table.put(font, fm = new iFontMetrics(font)); | ||
| 250 | } | ||
| 251 | return fm; | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | Returns a representation of this <code>FontMetric</code> | ||
| 256 | object's values as a string. | ||
| 257 | @return a string representation of this font metric. | ||
| 258 | */ | ||
| 259 | public String toString() { | ||
| 260 | return getClass().getName() + "[font=" + getFont() + "ascent=" + | ||
| 261 | getAscent() + ", descent=" + getDescent() + ", leading=" + | ||
| 262 | getLeading() + ", height=" + getHeight() + ", maxAdvance=" + | ||
| 263 | maxAdvance + ", font.getPeer()=" + font.getPeer().toString() + | ||
| 264 | " ]" ; | ||
| 265 | } | ||
| 266 | } | ||