freetype curve extraction in Font.java and readback in Box.java
authoradam <adam@megacz.com>
Sun, 2 May 2004 23:27:22 +0000 (23:27 +0000)
committeradam <adam@megacz.com>
Sun, 2 May 2004 23:27:22 +0000 (23:27 +0000)
darcs-hash:20040502232722-5007d-76c43eeb2ba9d4928a135dbef2f94585ffd3f1e8.gz

src/org/ibex/core/Box.java
src/org/ibex/graphics/Font.java
src/org/ibex/graphics/Freetype.c
src/org/ibex/graphics/Path.java

index 2fb9fe6..0e95a7e 100644 (file)
@@ -468,7 +468,13 @@ public final class Box extends JSScope implements Task {
         case "indexof": return METHOD;
         case "distanceto": return METHOD;
         case "text": return text;
-        case "path": throw new JSExn("cannot read from the path property");
+        case "path": 
+            if (path != null) return path.toString();
+            if (text == null) return null;
+            if (font == null) return null;
+            String ret = "";
+            for(int i=0; i<text.length(); i++) ret += font.glyphs[text.charAt(i)].path;
+            return ret;
         case "fill": return Color.colorToString(fillcolor);
         case "strokecolor": return Color.colorToString(strokecolor);
         case "textcolor": return Color.colorToString(strokecolor);
@@ -551,7 +557,7 @@ public final class Box extends JSScope implements Task {
         case "shrink":      CHECKSET_FLAG(HSHRINK | VSHRINK); RECONSTRAIN();
         case "hshrink":     CHECKSET_FLAG(HSHRINK); RECONSTRAIN();
         case "vshrink":     CHECKSET_FLAG(VSHRINK); RECONSTRAIN();
-        case "path":        path = Path.parse(toString(value)); dirty();
+        case "path":        path = Path.parse(toString(value)); RECONSTRAIN(); dirty();
         case "width":       setWidth(toInt(value), toInt(value));
         case "height":      setHeight(toInt(value), toInt(value));
         case "maxwidth":    setWidth(minwidth, toInt(value));
index 2b8b13c..9870aa6 100644 (file)
@@ -21,7 +21,7 @@ public class Font {
     public int max_ascent;                      ///< the maximum ascent, in pixels
     public int max_descent;                     ///< the maximum descent, in pixels
     boolean latinCharsPreloaded = false;        ///< true if a request to preload ASCII 32-127 has begun
-    Glyph[] glyphs = new Glyph[65535];          ///< the glyphs that comprise this font
+    public Glyph[] glyphs = new Glyph[65535];          ///< the glyphs that comprise this font
 
     public abstract static class Glyph {
         protected Glyph(Font font, char c) { this.font = font; this.c = c; }
@@ -33,6 +33,7 @@ public class Font {
         public int width = -1;                  ///< the width of the glyph
         public int height = -1;                 ///< the height of the glyph
         public byte[] data = null;              ///< the alpha channel samples for this font
+        public String path = null; // FIXME this should be shared across point sizes
         void render() {
             if (!isLoaded) try { renderGlyph(this); } catch (IOException e) { Log.info(Font.class, e); }
             isLoaded = true;
@@ -167,11 +168,16 @@ public class Font {
             
             glyph.width = rt.getUserInfo(1);
             glyph.height = rt.getUserInfo(2);
-            
+
             glyph.data = new byte[glyph.width * glyph.height];
             int addr = rt.getUserInfo(0);
             rt.copyin(addr, glyph.data, glyph.width * glyph.height);
             
+            byte[] path = new byte[rt.getUserInfo(8)];
+            rt.copyin(rt.getUserInfo(7), path, rt.getUserInfo(8));
+            glyph.path = new String(path);
+            glyph.path += " m " + (64 * glyph.advance) + " 0 "; 
+
             glyph.isLoaded = true;
         } catch (Exception e) {
             // FEATURE: Better error reporting (thow an exception?)
index 4387aec..62a2f7c 100644 (file)
@@ -119,6 +119,53 @@ int load_font(char *buf, int length) {
     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;
@@ -136,6 +183,17 @@ int render(int charcode, int size) {
     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
index 7c0fd40..7557209 100644 (file)
@@ -37,6 +37,12 @@ public class Path {
     static final byte TYPE_QUADRADIC = 4;
 
     public static Path parse(String s) { return Tokenizer.parse(s); }
+
+    // FIXME: hack
+    private String toString;
+    private Path(String s) { this.toString = s; }
+    public String toString() { return toString; }
+
     public static class Tokenizer {
         // FIXME: check array bounds exception for improperly terminated string
         String s;
@@ -47,7 +53,7 @@ public class Path {
         public static Path parse(String s) {
             if (s == null) return null;
             Tokenizer t = new Tokenizer(s);
-            Path ret = new Path();
+            Path ret = new Path(s);
             char last_command = 'M';
             boolean first = true;
             while(t.hasMoreTokens()) {