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