34 |
* of an example - other implementations should work on sharing code. |
* of an example - other implementations should work on sharing code. |
35 |
*/ |
*/ |
36 |
public class SimpleAlphaFont { |
public class SimpleAlphaFont { |
37 |
|
public static boolean dbg = false; |
38 |
|
private static void pa(String s) { System.out.println(s); } |
39 |
|
|
40 |
// Even though it's wasteful, allocates all tiles. |
// Even though it's wasteful, allocates all tiles. |
41 |
static public Mosaic2D.Tile[] generateTiles(int[] chars, int[] meas, int border) { |
static public Mosaic2D.Tile[] generateTiles(int[] chars, int[] meas, int border) { |
158 |
return new GLFont(height, yoffs, widths, quadFont); |
return new GLFont(height, yoffs, widths, quadFont); |
159 |
|
|
160 |
} |
} |
161 |
|
|
162 |
|
static private int toint(byte a) { |
163 |
|
if(a < 0) return a + 256; |
164 |
|
return a; |
165 |
|
} |
166 |
|
static private byte tobyte(int a) { |
167 |
|
if(a > 127) return (byte)(a - 256); |
168 |
|
return (byte)a; |
169 |
|
} |
170 |
|
static private byte avg(byte a, byte b) { |
171 |
|
return tobyte((toint(a) + toint(b))/2); |
172 |
|
} |
173 |
|
|
174 |
|
static private void shrinkX(byte[] data, int width, int height, int fac) { |
175 |
|
if(fac != 2) throw new Error("!!!"); |
176 |
|
for(int i=0; i<data.length / 2; i++) |
177 |
|
data[i] = avg(data[2*i], data[2*i+1]); |
178 |
|
} |
179 |
|
|
180 |
|
static private void shrinkY(byte[] data, int width, int height, int fac) { |
181 |
|
if(fac != 2) throw new Error("!!!"); |
182 |
|
for(int y=0; y<height/2; y++) { |
183 |
|
for(int x=0; x<width; x++) { |
184 |
|
data[x+width*y] = avg(data[x+width*(2*y)], data[x+width*(2*y+1)]); |
185 |
|
} |
186 |
|
} |
187 |
|
} |
188 |
|
|
189 |
|
/** Post-process a quadfont by reducing resolution by n in the given direction. |
190 |
|
* Useful for aniso font experiments, where we want to |
191 |
|
* retain the exact same layout in the mipmaps, not much else. |
192 |
|
*/ |
193 |
|
static public void postprocessGLFont_reduceReso(GL.QuadFont f, int xfac, int yfac) { |
194 |
|
if(xfac <= 0 || yfac <= 0) throw new Error("Not allowed: "+xfac+" "+yfac); |
195 |
|
if(xfac > 1 && yfac > 1) { |
196 |
|
postprocessGLFont_reduceReso(f, xfac, 1); |
197 |
|
postprocessGLFont_reduceReso(f, 1, yfac); |
198 |
|
} |
199 |
|
GL.Texture[] textures = f.getTextures(); |
200 |
|
for(int i=0; i<textures.length; i++) { |
201 |
|
int width = (int)(textures[i].getLevelParameter(0, "TEXTURE_WIDTH")[0]); |
202 |
|
int height = (int)(textures[i].getLevelParameter(0, "TEXTURE_HEIGHT")[0]); |
203 |
|
byte[] tex = new byte[width * height]; |
204 |
|
textures[i].getTexImage(0, "ALPHA", "UNSIGNED_BYTE", tex); |
205 |
|
|
206 |
|
if(xfac > 1) |
207 |
|
shrinkX(tex, width, height, xfac); |
208 |
|
if(yfac > 1) |
209 |
|
shrinkY(tex, width, height, yfac); |
210 |
|
|
211 |
|
textures[i].texImage2D(0, "ALPHA", width / xfac, height / yfac, 0, |
212 |
|
"ALPHA", "UNSIGNED_BYTE", tex); |
213 |
|
|
214 |
|
} |
215 |
|
} |
216 |
|
|
217 |
|
/** Get a DrawPixels gl renderable for drawing the actual texels |
218 |
|
* of a given level for a given character using a GL_LUMINANCE mapping. |
219 |
|
*/ |
220 |
|
static public org.nongnu.libvob.Vob getLevelDrawPixels(GL.QuadFont f, int glyph, int lod) { |
221 |
|
GL.Texture[] textures = f.getTextures(); |
222 |
|
float[] meas = f.getMeasurements(glyph); |
223 |
|
GL.Texture tex = textures[(int)meas[0]]; |
224 |
|
|
225 |
|
float tx0 = meas[5]; |
226 |
|
float ty0 = meas[6]; |
227 |
|
float tx1 = meas[7]; |
228 |
|
float ty1 = meas[8]; |
229 |
|
|
230 |
|
int width = (int)(tex.getLevelParameter(lod, "TEXTURE_WIDTH")[0]); |
231 |
|
int height = (int)(tex.getLevelParameter(lod, "TEXTURE_HEIGHT")[0]); |
232 |
|
byte[] data = new byte[width * height]; |
233 |
|
tex.getTexImage(lod, "ALPHA", "UNSIGNED_BYTE", data); |
234 |
|
|
235 |
|
int x = (int)(tx0 * width); |
236 |
|
int w = (int)Math.ceil(tx1 * width) - x; |
237 |
|
|
238 |
|
int y = (int)(ty0 * height); |
239 |
|
int h = (int)Math.ceil(ty1 * height) - y; |
240 |
|
|
241 |
|
byte[] ndata = new byte[w*h]; |
242 |
|
for(int xi = 0; xi < w; xi ++) { |
243 |
|
for(int yi = 0; yi < h; yi ++) { |
244 |
|
ndata[xi + w*yi] = data[x + xi + width * (y + yi)]; |
245 |
|
} |
246 |
|
} |
247 |
|
GL.ByteVector v = GL.createByteVector(w*h); |
248 |
|
v.set(ndata); |
249 |
|
|
250 |
|
pa("getleveldp: "+glyph+" "+lod+" "+x+" "+y+" "+w+" "+h); |
251 |
|
if(dbg) if(w < 20 && h < 20) { |
252 |
|
StringBuffer s = new StringBuffer(); |
253 |
|
StringBuffer s0 = new StringBuffer(); |
254 |
|
StringBuffer s1 = new StringBuffer(); |
255 |
|
for(int i=0; i<w*h; i++){ |
256 |
|
s.append(" "); |
257 |
|
s.append(v.get(i)); |
258 |
|
s0.append(" "); |
259 |
|
s0.append(ndata[i]); |
260 |
|
} |
261 |
|
pa(""+s); |
262 |
|
pa(""+s0); |
263 |
|
} |
264 |
|
|
265 |
|
return GLRen.createDrawPixels(w, h, "LUMINANCE", "UNSIGNED_BYTE", v); |
266 |
|
|
267 |
|
} |
268 |
|
|
269 |
} |
} |
270 |
|
|
271 |
|
|
272 |
|
|