1    package org.xwt.imp;
2    import org.xwt.*;
3    import org.xwt.util.*;
4    import java.io.*;
5    
6    public class Font {
7    
8        private static final int OURWIDTH=512;
9        private static final int OURHEIGHT=128;
10       private static byte[] rendering = new byte[OURWIDTH*OURHEIGHT];
11       
12       private static MIPSInterpreter vm = null;
13       private static class FontDecoder extends ImageDecoder {
14   	int[] data = null;
15   	intintwidthheight;
16   	public int getWidth() { return width; }
17   	public int getHeight() { return height; }
18   	public int[] getData() { return data; }
19       }
20   
21       /** k1 is the resource that the font came from; k2 is the size (Integer) */
22       Cache cache = new Cache();
23   
24       /** contains all the glyphs */
25       Picture fontPicture = null;
26   
27       // FIXME: need kerning pairs
28   
29       /** bounding boxen of the glyphs (indexed by glyph) */
30       int[] bbox_x;
31       int[] bbox_y;
32       int[] bbox_w;
33       int[] bbox_h;
34       int[] advance;
35   
36       int ascender;
37       int descender;
38   
39       public static synchronized ImageDecoder render(InputStream is, int size, String text, boolean sizeOnly) throws Exception{
40   
41   	if (vm == null) {
42   	    vm = new MIPSInterpreter("freetype.mips");
43   	    vm.start(new String[]{ "freetype.mips"});
44   	    vm.execute();
45   	}
46   
47   	int FONT_RESERVED = 256*1024;
48   	int RENDER_RESERVED = OURWIDTH * OURHEIGHT;
49   	int STRING_RESERVED = 1024;
50   	int baseAddr = vm.sbrk(FONT_RESERVED + RENDER_RESERVED + STRING_RESERVED);
51   	int renderAddr = baseAddr + FONT_RESERVED;
52   	int stringAddr = renderAddr + RENDER_RESERVED;
53   
54   	byte[] font = Resources.isToByteArray(is);
55   
56   	vm.copyout(font, baseAddr, font.length);
57   	vm.setUserInfo(0, baseAddr);
58   	vm.setUserInfo(1, font.length);
59   	vm.setUserInfo(2, renderAddr);
60   	vm.setUserInfo(3, stringAddr);
61   	vm.setUserInfo(4, size);
62           vm.setUserInfo(7, sizeOnly ? 1 : 0);
63   	
64   	// hack because (believe it or not) libgcj doesn't support UTF16.
65   	byte[] b = new byte[text.length() * 2 + 2];
66   	for(int i=0; i<text.length(); i++) {
67   	    b[i * 2] = (byte)((((short)text.charAt(i)) & 0xff00) >> 8);
68   	    b[i * 2 + 1] = (byte)(((short)text.charAt(i)) & 0xff);
69   	}
70   	b[text.length()] = 0;
71   	b[text.length() + 1] = 0;
72   
73   	vm.copyout(b, stringAddr, Math.min(b.length, STRING_RESERVED));
74   	long start = System.currentTimeMillis();
75   	vm.execute();
76   	//Log.log(Font.class, "Render of: " + text + " took " + (System.currentTimeMillis()-start) + " ms");
77   	vm.copyin(renderAddr, rendering, rendering.length);
78   
79   	FontDecoder ret = new FontDecoder();
80   	ret.width = vm.getUserInfo(5);
81   	ret.height = vm.getUserInfo(6);
82   	ret.data = new int[ret.width * ret.height];
83           for(int i=0; i<ret.height; i++)
84               for(int j=0; j<ret.width; j++) {
85   		int val = rendering[i * OURWIDTH + j] & 0xff;
86                   ret.data[i * ret.width + j] = val << 24;
87   	    }
88   
89   	return ret;
90       }
91      
92   }
93