1
2 package org.xwt;
3
4 import java.io.*;
5 import java.util.*;
6 import org.xwt.util.*;
7
8
9 public class XWF {
10
11
12 private static Hash xwtfonts = new Hash();
13
14
15 int[] data = null;
16
17
18 int w = 0;
19
20
21 int h = 0;
22
23
24 String name = null;
25
26
27 int maxascent = 0;
28
29
30 int maxdescent = 0;
31
32
33 Hash pictures = new Hash();
34
35
43 int[][] metrics = null;
44
45
46 public static void flushXWFs() { xwtfonts.clear(); }
47
48
49 public static XWF getXWF(String resourcename) {
50 XWF ret = (XWF)xwtfonts.get(resourcename);
51 if (ret != null) return ret;
52
53 String resolved = Resources.resolve(resourcename + ".xwf", null);
54 byte[] bytes = Resources.getResource(resolved);
55 if (bytes != null) {
56 PNG png = PNG.decode(new ByteArrayInputStream(bytes), resourcename);
57 if (png != null) return new XWF(resourcename, png);
58 }
59 return null;
60 }
61
62 public int getMaxAscent() { return maxascent; }
63 public int getMaxDescent() { return maxdescent; }
64
65
66 public void drawString(DoubleBuffer buf, String text, int x, int y, int argb) {
67
68 Integer color = new Integer(argb | 0xFF000000);
69 Picture pg = (Picture)pictures.get(color);
70 if (pg == null) {
71 int[] data2 = new int[data.length];
72 for(int i=0; i<data.length; i++)
73 data2[i] = (data[i] & 0xFF000000) | (argb & 0x00FFFFFF);
74 pg = Platform.createPicture(data2, w, h);
75 pictures.put(color, pg);
76 }
77
78 int left = x;
79 for(int i=0; i<text.length(); i++) {
80 int c = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".indexOf(text.charAt(i));
81 if (c == -1 || metrics[c] == null) {
82 left += metrics[64] != null ? metrics[64][4] : 10;
83 continue;
84 }
85 buf.drawPicture(pg,
86 left,
87 y - (metrics[c][5] - metrics[c][2]),
88 left + metrics[c][1] - metrics[c][0],
89 y - (metrics[c][5] - metrics[c][2]) + metrics[c][3] - metrics[c][2],
90 metrics[c][0], metrics[c][2], metrics[c][1], metrics[c][3]);
91
92 left += metrics[c][4];
93 }
94 }
95
96
97 public int stringWidth(String text) {
98 int ret = 0;
99 for(int i=0; i<text.length(); i++) {
100
101 int c = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".indexOf(text.charAt(i));
102 if (c == -1 || metrics[c] == null) { ret += metrics[64][4]; continue; }
103 ret += metrics[c][4];
104 }
105 return ret;
106 }
107
108 private XWF(String name, PNG png) {
109 this.name = name;
110 xwtfonts.put(name, this);
111
112 data = png.getData();
113 w = png.getWidth();
114 h = png.getHeight();
115
116 intintint y1;
117 boolean breakout;
118
119 intintintintintart_y, end_x, end_y, advance;
120
121 int[] rows = new int[120];
122
123 int baseline = 0;
124
125 metrics = new int[96][];
126 int numglyphs = 0;
127
128 for(y=0; y<h; y++) {
129
130
131 for(breakout = false; y<h && !breakout; y++)
132 for(x = 0; x<w; x++)
133 if ((data[x + y * w] & 0x00FFFFFF) != 0x00FFFFFF) breakout = true;
134
135 start_y = y - 2;
136
137
138 for(breakout = false; y<h && !breakout; y++)
139 for(x = 0, breakout = true; x<w; x++)
140 if ((data[x + y * w] & 0x00FFFFFF) != 0x00FFFFFF) breakout = false;
141
142 end_y = y;
143
144 if (start_y == end_y) continue;
145
146 for(x=0; x<w; x++) {
147
148
149 for(breakout = false; x<w && !breakout; x++)
150 for(y1 = start_y; y1<end_y; y1++)
151 if (Math.abs(((data[x + y1 * w] & 0x00FF0000) >> 16) - ((data[x + y1 * w] & 0x0000FF00) >> 8)) > 10 ||
152 Math.abs(((data[x + y1 * w] & 0x0000FF00) >> 8) - ((data[x + y1 * w] & 0x000000FF))) > 10) {
153 breakout = true;
154 baseline = y1;
155 }
156
157
158 for(breakout = false; x<w && !breakout; x++)
159 for(y1 = start_y, breakout = true; y1<end_y; y1++)
160 if (Math.abs(((data[x + y1 * w] & 0x00FF0000) >> 16) - ((data[x + y1 * w] & 0x0000FF00) >> 8)) > 10 ||
161 Math.abs(((data[x + y1 * w] & 0x0000FF00) >> 8) - ((data[x + y1 * w] & 0x000000FF))) > 10) {
162 breakout = false;
163 }
164
165 x--;
166 start_x = x;
167
168
169 for(breakout = false; x<w && !breakout; x++)
170 for(y1 = start_y; y1<end_y; y1++)
171 if (Math.abs(((data[x + y1 * w] & 0x00FF0000) >> 16) - ((data[x + y1 * w] & 0x0000FF00) >> 8)) > 10 ||
172 Math.abs(((data[x + y1 * w] & 0x0000FF00) >> 8) - ((data[x + y1 * w] & 0x000000FF))) > 10) {
173 breakout = true;
174 baseline = y1;
175 }
176
177 x--;
178 advance = x - start_x;
179
180
181 for(breakout = false; x<w && !breakout; x++)
182 for(y1 = start_y, breakout = true; y1<end_y; y1++)
183 if (Math.abs(((data[x + y1 * w] & 0x00FF0000) >> 16) - ((data[x + y1 * w] & 0x0000FF00) >> 8)) > 10 ||
184 Math.abs(((data[x + y1 * w] & 0x0000FF00) >> 8) - ((data[x + y1 * w] & 0x000000FF))) > 10) {
185 breakout = false;
186 }
187
188 x--;
189 end_x = x;
190
191 if (start_x == end_x) break;
192
193 metrics[numglyphs] = new int[6];
194 metrics[numglyphs][0] = start_x;
195 metrics[numglyphs][1] = end_x;
196 metrics[numglyphs][2] = start_y;
197 metrics[numglyphs][3] = end_y;
198 metrics[numglyphs][4] = advance;
199 metrics[numglyphs][5] = baseline;
200 numglyphs++;
201
202 if (numglyphs >= metrics.length) break;
203
204 }
205
206 if (numglyphs >= metrics.length) break;
207 }
208
209 for(int i=0; i<data.length; i++)
210 if (Math.abs(((data[i] & 0x00FF0000) >> 16) - ((data[i] & 0x0000FF00) >> 8)) > 10 ||
211 Math.abs(((data[i] & 0x0000FF00) >> 8) - ((data[i] & 0x000000FF))) > 10)
212 data[i] = 0x00;
213 else
214 data[i] = (0xFF - (data[i] & 0xFF)) << 24;
215
216 for(int i=33; i<=126; i++)
217 if (metrics[i - 33] != null)
218 maxascent = Math.max(maxascent, metrics[i - 33][5] - metrics[i - 33][2]);
219
220 for(int i=33; i<=126; i++)
221 if (metrics[i - 33] != null)
222 maxdescent = Math.max(maxdescent, metrics[i - 33][3] - metrics[i - 33][5]);
223
224 }
225
226 }
227