1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
4 #include <freetype/freetype.h>
6 /* NOTE: _user_info is defined in crt0.c. It points to a 4096 byte
7 block of memory that contains 1024 32-bit values that can be set
8 with the setUserInfo() method of MIPSEmu.
10 The VM will pause after initialization. When unpaused, it expects
13 user_info[0] = ptr to font byte stream in memory
14 user_info[1] = length of font stream
15 user_info[2] = unicode index of first glyph to render
16 user_info[3] = unicode index of last glyph to render
17 user_info[4] = point size to render in
19 The VM will then iterate over the requested glyphs, performing the
20 following actions for each glyph:
23 - store the address of the glyph bitmap in user_info[5]
24 - store the width of the glyph bitmap in user_info[6]
25 - store the height of the glyph bitmap in user_info[7]
26 - store the font's ascender into user_info[8]
27 - store the font's height into user_info[9]
28 - store the glyph's ascender into user_info[10]
29 - store the glyph's advance into user_info[11]
31 The VM will then pause after each glyph. The VM should not be
32 unpaused after the last glyph until the next glyph set has been
33 configured in user_info (ie it does not pause twice).
38 extern int user_info[1024];
40 /* HACK: This really doesn't belong here... */
43 extern int mspack_main();
46 int main(int argc, char **argv) {
47 if(argc < 1) return 1;
48 if(strcmp(argv[0],"mspack")==0) return mspack_main();
49 if(strcmp(argv[0],"freetype")==0) return freetype_main();
55 #define FT_Check(expr) do { \
57 errprint(#expr " failed\n"); \
62 #define max(a, b) ((a) > (b) ? (a) : (b))
63 #define min(a, b) ((a) < (b) ? (a) : (b))
65 static int errprint(const char *s) {
69 n = write(STDERR_FILENO,s,l);
79 static FT_Library library; /* handle to library */
80 static FT_Face face; /* handle to face object */
83 FT_Check(FT_Init_FreeType(&library));
91 FT_Check(FT_Init_FreeType(&library));
96 FT_Check(FT_Set_Char_Size(face, 0, ((int)user_info[4]) * 64, 72, 72));
97 for(charcode = (int)user_info[2]; charcode <= (int)user_info[3]; charcode++) {
99 glyph_index = FT_Get_Char_Index(face, charcode);
100 FT_Check(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT));
101 FT_Check(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL));
103 user_info[5] = (char*)face->glyph->bitmap.buffer;
104 user_info[6] = (char*)face->glyph->bitmap.width;
105 user_info[7] = (char*)face->glyph->bitmap.rows;
106 user_info[8] = (char*)(face->size->metrics.ascender >> 6);
107 user_info[9] = (char*)((-1 * face->size->metrics.descender) >> 6);
108 user_info[10] = (char*)(face->glyph->metrics.horiBearingY >> 6);
109 user_info[11] = (char*)(face->glyph->advance.x >> 6);
115 int load_font(char *buf, int length) __attribute__((section(".text")));
116 int load_font(char *buf, int length) {
117 if(face != NULL) FT_Check(FT_Done_Face(face));
119 return FT_New_Memory_Face(library, buf, length, 0, &face);
122 int render(int charcode, int size) __attribute__((section(".text")));
123 int render(int charcode, int size) {
126 FT_Check(FT_Set_Char_Size(face, 0, size * 64, 72, 72));
128 glyph_index = FT_Get_Char_Index(face, charcode);
129 FT_Check(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT));
130 FT_Check(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL));
132 user_info[0] = (int)face->glyph->bitmap.buffer;
133 user_info[1] = face->glyph->bitmap.width;
134 user_info[2] = face->glyph->bitmap.rows;
135 user_info[3] = face->size->metrics.ascender >> 6;
136 user_info[4] = (-1 * face->size->metrics.descender) >> 6;
137 user_info[5] = face->glyph->metrics.horiBearingY >> 6;
138 user_info[6] = face->glyph->advance.x >> 6;
141 // Kerning code; add back in later
143 if (old_glyph_index != -1) {
144 if (FT_HAS_KERNING(face)) {
145 FT_Check(FT_Get_Kerning(face, old_glyph_index, glyph_index, 0, &kerning));
148 x += face->glyph->advance.x >> 6;
151 old_glyph_index = glyph_index;