temporarily disabled clipping
[org.ibex.core.git] / src / org / ibex / core / Box.java
index 76871cf..595e101 100644 (file)
@@ -9,9 +9,15 @@ package org.ibex.core;
 // FIXME: mouse move/release still needs to propagate to boxen in which the mouse was pressed and is still held down
 // FEATURE: reintroduce surface.abort
 
+// Broken:
+// - textures
+// - align/origin
+// - clipping (all forms)
+
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.plat.*;
 import org.ibex.graphics.*;
 
 /**
@@ -33,7 +39,11 @@ import org.ibex.graphics.*;
  *  trigger a Surface.abort; if rendering were done in the same pass,
  *  rendering work done prior to the Surface.abort would be wasted.
  */
-public final class Box extends JS.Obj implements Callable {
+public final class Box extends JS.Obj implements Callable, Mesh.Chain {
+
+    public Mesh.Chain getMeshChainParent() { return parent; }
+    public Mesh       getMesh()            { return mesh; }
+    public Affine     getAffine()          { return transform; }
 
     // Macros //////////////////////////////////////////////////////////////////////
 
@@ -59,10 +69,12 @@ public final class Box extends JS.Obj implements Callable {
     private int          strokecolor  = 0xFF000000;
     public  float        flex         = 1;
     private Path         path         = null;
+    private Path         clippath     = null;
     private Affine       transform    = Affine.identity();
 
     // FEATURE: polygon caching
-    private Polygon      polygon      = null;
+    private Mesh      polygon      = null;
+    private Mesh         mesh         = null;
 
     // specified directly by user
     public int minwidth = 0;
@@ -94,7 +106,7 @@ public final class Box extends JS.Obj implements Callable {
     public void dirty() { if (path==null) dirty(0, 0, contentwidth, contentheight); else dirty(path); }
     public void dirty(int x, int y, int w, int h) { }
     public void dirty(Path p) {
-        Affine a = transform;
+        Affine a = transform.copy();
         for(Box cur = this; cur != null; cur = cur.parent) a.premultiply(cur.transform);
         long hbounds = p.horizontalBounds(a);
         long vbounds = p.verticalBounds(a);
@@ -121,8 +133,8 @@ public final class Box extends JS.Obj implements Callable {
     void place() {
         if (!packed()) {
             for(Box child = getChild(0); child != null; child = child.nextSibling()) {
-                child.width = max(child.minwidth, child.test(HSHRINK) ? child.contentwidth : child.maxwidth);
-                child.height = max(child.minheight, child.test(VSHRINK) ? child.contentheight : child.maxheight);
+                child.width = max(child.minwidth, min(child.test(HSHRINK) ? child.contentwidth : width, child.maxwidth));
+                child.height = max(child.minheight, min(child.test(VSHRINK) ? child.contentheight : height, child.maxheight));
                 child.place();
             }
             return;
@@ -165,7 +177,8 @@ public final class Box extends JS.Obj implements Callable {
         transform.f = 0;
         a = a.copy().premultiply(transform);
 
-        boolean relevant = packed() || ((fillcolor&0xff000000)!=0x0) || path!=null;
+        //boolean relevant = packed() || ((fillcolor&0xff000000)!=0x0) || path!=null;
+        boolean relevant = true;
         int save_xmin = xmin, save_ymin = ymin, save_xmax = xmax, save_ymax = ymax;
         if (!relevant) {
             for(Box child = getChild(0); child != null; child = child.nextSibling()) {
@@ -191,10 +204,8 @@ public final class Box extends JS.Obj implements Callable {
         xmax = save_xmax;
         ymax = save_ymax;
 
-        contentwidth  = bound(minwidth, contentwidth, maxwidth);
-        contentheight = bound(minheight, contentheight, maxheight);
-
-        int cw = bound(minwidth, contentwidth, maxwidth), ch = bound(minheight, contentheight, maxheight);
+        int cw = contentwidth = bound(minwidth, contentwidth, maxwidth);
+        int ch = contentheight = bound(minheight, contentheight, maxheight);
         //#repeat contentwidth/contentheight contentheight/contentwidth minwidth/minheight row/col col/row \
         //        textwidth/textheight maxwidth/maxheight bounds/boundsy x1/y1 x2/y2 z1/q1 z2/q2 z3/q3 z4/q4 \
         //        horizontalBounds/verticalBounds e/f multiply_px/multiply_py xmin/ymin xmax/ymax
@@ -214,35 +225,34 @@ public final class Box extends JS.Obj implements Callable {
     private static final boolean OPTIMIZE = false;
 
     /** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */
-    public void render(int cx1, int cy1, int cx2, int cy2, PixelBuffer buf, Affine a) {
+    public void render(PixelBuffer buf, Affine a, Mesh clipFrom) { render(buf, a, clipFrom, Affine.identity()); }
+    public void render(PixelBuffer buf, Affine a, Mesh clipFrom, Affine clipa) {
         if (!test(VISIBLE)) return;
-        a = a.copy().premultiply(transform);
-
-        // FIXME: clipping
-        if (path == null) {
-            if (((fillcolor & 0xFF000000) != 0x00000000 || parent == null)) {
-                if (OPTIMIZE && a.doesNotRotate()) {
-                    int x = (int)a.multiply_px(0, 0);
-                    int y = (int)a.multiply_py(0, 0);
-                    int x2 = (int)a.multiply_px(contentwidth, contentheight);
-                    int y2 = (int)a.multiply_py(contentwidth, contentheight);
-                    buf.fillTrapezoid(x, x, y, x2, x2, y2, (fillcolor & 0xFF000000) == 0 ? 0xffffffff : fillcolor);
-                } else {
-                    new Polygon().addrect(0, 0, contentwidth, contentheight, a).fill(buf, new Paint.SingleColorPaint(fillcolor));
-                }
+        a = a.copy().multiply(transform);
+        clipa = clipa.copy().multiply(transform);
+
+        if (mesh == null)
+            if (path != null) mesh = new Mesh(path, true);
+            else {
+                if (((fillcolor & 0xFF000000) != 0x00000000 || parent == null) && (text==null||"".equals(text)))
+                    mesh = new Mesh().addRect(0, 0, contentwidth, contentheight);
+                // long ret = font.rasterizeGlyphs(text, buf, a, null, 0x777777, 0);
+                // minwidth = maxwidth = font.textwidth(text);
+                // minheight = maxheight = font.textwidth(text);
+                // if (ret == 0) Platform.Scheduler.add(this);
+                // FIXME: texture
             }
-            // FIXME: text
-            // FIXME: texture
-        } else {
-            Polygon p = new Polygon(path, a);
-            p.fill(buf, new Paint.SingleColorPaint(fillcolor));
-            p.stroke(buf, strokecolor);
+        if (mesh==null) {
+            for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(buf, a, clipFrom, clipa);
+            return;
         }
 
-        for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(cx1, cy1, cx2, cy2, buf, a);
+        //if (clipFrom != null) clipFrom.subtract(mesh, clipa);
+        Mesh mesh = treeSize() > 0 ? this.mesh.copy() : this.mesh;
+        for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(buf, a, mesh, Affine.identity());
+        mesh.fill(buf, a, null, fillcolor, true);
     }
     
-    
     // Methods to implement org.ibex.js.JS //////////////////////////////////////
   
     public JS call(JS method, JS[] args) throws JSExn {
@@ -252,8 +262,7 @@ public final class Box extends JS.Obj implements Callable {
                 case "indexof":
                     Box b = (Box)args[0];
                     if (b.parent != this)
-                        return (redirect == null || redirect == this) ?
-                            JSU.N(-1) : redirect.call(method, args);
+                        return (redirect == null || redirect == this) ? JSU.N(-1) : redirect.call(method, args);
                     return JSU.N(b.getIndexInParent());
 
                 case "distanceto":
@@ -353,13 +362,23 @@ public final class Box extends JS.Obj implements Callable {
         if (JSU.isInt(name)) { put(JSU.toInt(name), value); return; }
         //#switch(JSU.toString(name))
         case "thisbox":     if (value == null) removeSelf();
-        case "text":        { String s = value==null ?  "" : JSU.toString(value); CHECKSET_STRING(text); RECONSTRAIN(); dirty(); }
+        case "text":        {
+            String s = value==null ?  "" : JSU.toString(value);
+            text = s;
+            minwidth = maxwidth = font.textwidth(text);
+            System.out.println("width=" + width);
+            minheight = maxheight = font.textheight(text);
+            System.out.println("height=" + height);
+            RECONSTRAIN();
+            dirty();
+        }
         case "strokecolor": value = JSU.N(Color.stringToColor(JSU.toString(value))); CHECKSET_INT(strokecolor); dirty();
         case "textcolor":   value = JSU.N(Color.stringToColor(JSU.toString(value))); CHECKSET_INT(strokecolor); dirty();
         case "shrink":      CHECKSET_FLAG(HSHRINK | VSHRINK); RECONSTRAIN();
         case "hshrink":     CHECKSET_FLAG(HSHRINK); RECONSTRAIN();
         case "vshrink":     CHECKSET_FLAG(VSHRINK); RECONSTRAIN();
         case "path":        {
+            mesh = null;
             path = new Path(JSU.toString(value));
             float tx = -1 * Encode.longToFloat2(path.horizontalBounds(Affine.identity()));
             float ty = -1 * Encode.longToFloat2(path.verticalBounds(Affine.identity()));
@@ -369,11 +388,22 @@ public final class Box extends JS.Obj implements Callable {
             dirty();
             polygon = null;
         }
+        case "clippath":        {
+            clippath = new Path(JSU.toString(value));
+            //float tx = -1 * Encode.longToFloat2(clippath.horizontalBounds(Affine.identity()));
+            //float ty = -1 * Encode.longToFloat2(clippath.verticalBounds(Affine.identity()));
+            //clippath.transform(Affine.translate(tx, ty), true);
+            REPLACE();
+            RECONSTRAIN();
+            dirty();
+            polygon = null;
+        }
         case "transform":   {
             transform = Affine.parse(JSU.toString(value));
             transform.e = 0;
             transform.f = 0;
-            if (getSurface() != null) getSurface().dirty(0, 0, 500, 500); // FIXME
+            if (getSurface() != null)  // FIXME
+                getSurface().dirty(0, 0, getSurface().root.contentwidth, getSurface().root.contentheight);
             REPLACE();
             RECONSTRAIN(); dirty(); polygon = null;
         }