import org.ibex.js.*;
import org.xwt.mips.*;
import org.ibex.plat.*;
+import org.xwt.mips.Runtime;
// FEATURE: this could be cleaner
/** encapsulates a single font (a set of Glyphs) */
// FEATURE: use streams, not memoryfont's
// FEATURE: kerning pairs
- private static int mem_allocated = 0;
- private static org.xwt.mips.Runtime vm = null;
- private static Stream loadedStream = null;
+ private static final Runtime rt;
+ private static Stream loadedStream;
+ private static int loadedStreamAddr;
- public static void loadFontByteStream(Stream res) {
+ static {
+ try {
+ rt = (Runtime)Class.forName("org.ibex.util.MIPSApps").newInstance();
+ } catch(Exception e) {
+ throw new Error("Error instansiating freetype");
+ }
+ rt.start(new String[]{"freetype"});
+ rt.execute();
+ rtCheck();
+ }
+
+ private static void rtCheck() { if(rt.getState() != Runtime.PAUSED) throw new Error("Freetype exited " + rt.exitStatus()); }
+
+ private static void loadFontByteStream(Stream res) {
+ if(loadedStream == res) return;
+
try {
Log.info(Font.class, "loading font " + res);
- loadedStream = res;
InputStream is = Stream.getInputStream(res);
byte[] fontstream = InputStreamToByteArray.convert(is);
- vm = (org.xwt.mips.Runtime)Class.forName("org.ibex.util.MIPSApps").newInstance();
- int baseAddr = vm.sbrk(fontstream.length);
- vm.copyout(fontstream, baseAddr, fontstream.length);
- vm.setUserInfo(0, baseAddr);
- vm.setUserInfo(1, fontstream.length);
- vm.start(new String[]{ "freetype" });
- vm.execute();
- if(vm.getState() == org.xwt.mips.Runtime.DONE) throw new Error("Freetype VM exited: " + vm.exitStatus());
+ rt.free(loadedStreamAddr);
+ loadedStreamAddr = rt.xmalloc(fontstream.length);
+ rt.copyout(fontstream, loadedStreamAddr, fontstream.length);
+ if(rt.call("load_font", loadedStreamAddr, fontstream.length) != 0)
+ throw new RuntimeException("load_font failed"); // FEATURE: better error
+ rtCheck();
+ loadedStream = res;
} catch (Exception e) {
+ // FEATURE: Better error reporting (thow an exception?)
Log.info(Font.class, e);
}
}
- public static synchronized void renderGlyph(Font.Glyph glyph) throws IOException {
+ private static synchronized void renderGlyph(Font.Glyph glyph) throws IOException {
try {
Log.debug(Font.class, "rasterizing glyph " + glyph.c + " of font " + glyph.font);
if (loadedStream != glyph.font.stream) loadFontByteStream(glyph.font.stream);
- vm.setUserInfo(2, (int)glyph.c);
- vm.setUserInfo(3, (int)glyph.c);
- vm.setUserInfo(4, glyph.font.pointsize);
+
long start = System.currentTimeMillis();
- vm.execute();
- glyph.font.max_ascent = vm.getUserInfo(8);
- glyph.font.max_descent = vm.getUserInfo(9);
- glyph.baseline = vm.getUserInfo(10);
- glyph.advance = vm.getUserInfo(11);
- glyph.width = vm.getUserInfo(6);
- glyph.height = vm.getUserInfo(7);
+ rt.call("render",glyph.c,glyph.font.pointsize);
+ rtCheck();
+
+ glyph.font.max_ascent = rt.getUserInfo(3);
+ glyph.font.max_descent = rt.getUserInfo(4);
+ glyph.baseline = rt.getUserInfo(5);
+ glyph.advance = rt.getUserInfo(6);
+
+ glyph.width = rt.getUserInfo(1);
+ glyph.height = rt.getUserInfo(2);
glyph.data = new byte[glyph.width * glyph.height];
- int addr = vm.getUserInfo(5);
- vm.copyin(addr, glyph.data, glyph.width * glyph.height);
- glyph.isLoaded = true;
+ int addr = rt.getUserInfo(0);
+ rt.copyin(addr, glyph.data, glyph.width * glyph.height);
+ glyph.isLoaded = true;
} catch (Exception e) {
+ // FEATURE: Better error reporting (thow an exception?)
Log.info(Font.class, e);
}
}
#include <unistd.h>
#include <freetype/freetype.h>
-char *user_info[1024];
-
/* NOTE: _user_info is defined in crt0.c. It points to a 4096 byte
block of memory that contains 1024 32-bit values that can be set
with the setUserInfo() method of MIPSEmu.
*/
+#if 0
+extern int user_info[1024];
+#else
+/* HACK: This really doesn't belong here... */
+int user_info[1024];
+
+extern int mspack_main();
+int freetype_main();
+
+int main(int argc, char **argv) {
+ if(argc < 1) return 1;
+ if(strcmp(argv[0],"mspack")==0) return mspack_main();
+ if(strcmp(argv[0],"freetype")==0) return freetype_main();
+ return 1;
+}
+#endif
+
+
#define FT_Check(expr) do { \
if((expr) != 0) { \
errprint(#expr " failed\n"); \
extern void _pause();
+static FT_Library library; /* handle to library */
+static FT_Face face; /* handle to face object */
+
int freetype_main() {
- char *fontdata;
+ FT_Check(FT_Init_FreeType(&library));
+ _pause();
+
+ /*char *fontdata;
int glyph_index;
short charcode;
- FT_Library library; /* handle to library */
- FT_Face face; /* handle to face object */
+
FT_Check(FT_Init_FreeType(&library));
- FT_Check(FT_New_Memory_Face(library, user_info[0], (int)user_info[1], 0, &face));
for(;;) {
user_info[11] = (char*)(face->glyph->advance.x >> 6);
}
- }
+ }*/
+}
+
+int load_font(char *buf, int length) __attribute__((section(".text")));
+int load_font(char *buf, int length) {
+ if(face != NULL) FT_Check(FT_Done_Face(face));
+ face = NULL;
+ return FT_New_Memory_Face(library, buf, length, 0, &face);
}
+int render(int charcode, int size) __attribute__((section(".text")));
+int render(int charcode, int size) {
+ int glyph_index;
+
+ FT_Check(FT_Set_Char_Size(face, 0, size * 64, 72, 72));
+
+ glyph_index = FT_Get_Char_Index(face, charcode);
+ FT_Check(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT));
+ FT_Check(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL));
+
+ user_info[0] = (int)face->glyph->bitmap.buffer;
+ user_info[1] = face->glyph->bitmap.width;
+ user_info[2] = face->glyph->bitmap.rows;
+ user_info[3] = face->size->metrics.ascender >> 6;
+ user_info[4] = (-1 * face->size->metrics.descender) >> 6;
+ user_info[5] = face->glyph->metrics.horiBearingY >> 6;
+ user_info[6] = face->glyph->advance.x >> 6;
+}
// Kerning code; add back in later
/*
}
old_glyph_index = glyph_index;
*/
-
-
-extern int mspack_main();
-int main(int argc, char **argv) {
- if(argc < 1) return 1;
- if(strcmp(argv[0],"mspack")==0) return mspack_main();
- if(strcmp(argv[0],"freetype")==0) return freetype_main();
- return 1;
-}