freetype curve extraction in Font.java and readback in Box.java
[org.ibex.core.git] / src / org / ibex / graphics / Freetype.c
index 2a1c798..62a2f7c 100644 (file)
 
 */
 
-extern char *user_info[1024];
+#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) { \
@@ -60,15 +76,19 @@ static int errprint(const char *s) {
 
 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(;;) {
       
@@ -89,9 +109,92 @@ int freetype_main() {
             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);
+}
+
+// if the path is more than 16k chars long, we're screwed anyways...
+static char path[1024 * 16];
+static int pathlen = 0;
+static int current_x;
+static int current_y;
+
+static void append(FT_Pos x, FT_Pos y) {
+    sprintf(path + pathlen, "%d,%d ", x - current_x, y - current_y);
+    pathlen += strlen(path + pathlen);
+}
+static int moveto(FT_Vector* to, void* user) {
+    if (pathlen > 0) {
+        path[pathlen++] = 'z';
+        path[pathlen++] = ' ';
     }
+    path[pathlen++] = 'm';
+    path[pathlen++] = ' ';
+    append(to->x, to->y);
+    current_x = to->x; current_y = to->y;
+    return 0;
+}
+static int lineto(FT_Vector* to, void* user) {
+    path[pathlen++] = 'l';
+    path[pathlen++] = ' ';
+    append(to->x, to->y);
+    current_x = to->x; current_y = to->y;
+    return 0;
+}
+static int conicto(FT_Vector* control, FT_Vector*  to, void* user) {
+    path[pathlen++] = 'q';
+    path[pathlen++] = ' ';
+    append(control->x, control->y);
+    append(to->x, to->y);
+    current_x = to->x; current_y = to->y;
+    return 0;
+}
+static int cubicto(FT_Vector* control1, FT_Vector* control2, FT_Vector* to, void* user) {
+    path[pathlen++] = 'c';
+    path[pathlen++] = ' ';
+    append(control1->x, control1->y);
+    append(control2->x, control2->y);
+    append(to->x, to->y);
+    current_x = to->x; current_y = to->y;
+    return 0;
 }
+static FT_Outline_Funcs buildPath = { &moveto, &lineto, &conicto, &cubicto, 0, 0 };
 
+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;
+
+    pathlen = 0; current_x = 0; current_y = 0;
+    FT_Outline_Decompose(&face->glyph->outline, &buildPath, NULL);
+    path[pathlen++] = 'z';
+    path[pathlen++] = ' ';
+    path[pathlen++] = 'm';
+    path[pathlen++] = ' ';
+    append(0, 0);
+    path[pathlen++] = ' ';
+    user_info[7] = (int)&path;
+    user_info[8] = pathlen;
+}
 
 // Kerning code; add back in later
 /*