changes made after tupshins reconstruction
[org.ibex.core.git] / src / org / xwt / VectorGraphics.java
index e028caa..988c18a 100644 (file)
@@ -1,3 +1,4 @@
+// FIXME
 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
 package org.xwt;
 import org.xwt.util.*;
@@ -40,6 +41,7 @@ public final class VectorGraphics {
     // Public entry points /////////////////////////////////////////////////////////////////
 
     public static VectorPath parseVectorPath(String s) {
+        if (s == null) return null;
         PathTokenizer t = new PathTokenizer(s);
         VectorPath ret = new VectorPath();
         char last_command = 'M';
@@ -78,6 +80,13 @@ public final class VectorGraphics {
        public static Affine flip(boolean horiz, boolean vert) { return new Affine(horiz ? -1 : 1, 0, 0, vert ? -1 : 1, 0, 0); }
         public float multiply_px(float x, float y) { return x * a + y * c + e; }
        public float multiply_py(float x, float y) { return x * b + y * d + f; }
+        public boolean equalsIgnoringTranslation(Affine x) { return a == x.a && b == x.b && c == x.c && d == x.d; }
+
+        public boolean equals(Object o) {
+            if (!(o instanceof Affine)) return false;
+            Affine x = (Affine)o;
+            return a == x.a && b == x.b && c == x.c && d == x.d && e == x.e && f == x.f;
+        }
 
        public static Affine rotate(float degrees) {
            float s = (float)Math.sin(degrees * (float)(Math.PI / 180.0));
@@ -112,6 +121,72 @@ public final class VectorGraphics {
 
     // PathTokenizer //////////////////////////////////////////////////////////////////////////////
 
+    public static Affine parseTransform(String t) {
+        if (t == null) return null;
+        t = t.trim();
+        Affine ret = VectorGraphics.Affine.identity();
+        while (t.length() > 0) {
+            if (t.startsWith("skewX(")) {
+                // FIXME
+                
+            } else if (t.startsWith("shear(")) {
+                // FIXME: nonstandard; remove this
+                ret.multiply(VectorGraphics.Affine.shear(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
+                
+            } else if (t.startsWith("skewY(")) {
+                // FIXME
+                
+            } else if (t.startsWith("rotate(")) {
+                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                if (sub.indexOf(',') != -1) {
+                    float angle = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
+                    sub = sub.substring(sub.indexOf(',') + 1);
+                    float cx = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
+                    sub = sub.substring(sub.indexOf(',') + 1);
+                    float cy = Float.parseFloat(sub);
+                    ret.multiply(VectorGraphics.Affine.translate(cx, cy));
+                    ret.multiply(VectorGraphics.Affine.rotate(angle));
+                    ret.multiply(VectorGraphics.Affine.translate(-1 * cx, -1 * cy));
+                } else {
+                    ret.multiply(VectorGraphics.Affine.rotate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
+                }
+                
+            } else if (t.startsWith("translate(")) {
+                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                if (sub.indexOf(',') > -1) {
+                    ret.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
+                                                                 Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
+                } else {
+                    ret.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))), 0));
+                }
+                
+            } else if (t.startsWith("flip(")) {
+                String which = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                ret.multiply(VectorGraphics.Affine.flip(which.equals("horizontal"), which.equals("vertical")));
+                
+            } else if (t.startsWith("scale(")) {
+                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                if (sub.indexOf(',') > -1) {
+                    ret.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
+                                                             Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
+                } else {
+                    ret.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
+                                                             Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(',')))));
+                }
+                
+            } else if (t.startsWith("matrix(")) {
+                // FIXME: is this mapped right?
+                float d[] = new float[6];
+                StringTokenizer st = new StringTokenizer(t, ",", false);
+                for(int i=0; i<6; i++)
+                    d[i] = Float.parseFloat(st.nextToken());
+                ret.multiply(new VectorGraphics.Affine(d[0], d[1], d[2], d[3], d[4], d[5]));
+            }
+            t = t.substring(t.indexOf(')') + 1).trim();
+        }
+        return ret;
+    }
+    
     public static final float PX_PER_INCH = 72;
     public static final float INCHES_PER_CM = (float)0.3937;
     public static final float INCHES_PER_MM = INCHES_PER_CM / 10;
@@ -191,20 +266,6 @@ public final class VectorGraphics {
        static final byte TYPE_CUBIC = 3;
        static final byte TYPE_QUADRADIC = 4;
 
-        // FEATURE: make this faster and cache it; also deal with negative coordinates
-        public int boundingBoxWidth() {
-            int ret = 0;
-            for(int i=0; i<numvertices; i++) ret = Math.max(ret, (int)Math.ceil(x[i]));
-            return ret;
-        }
-
-        // FEATURE: make this faster and cache it; also deal with negative coordinates
-        public int boundingBoxHeight() {
-            int ret = 0;
-            for(int i=0; i<numvertices; i++) ret = Math.max(ret, (int)Math.ceil(y[i]));
-            return ret;
-        }
-
         /** Creates a concrete vector path transformed through the given matrix. */
        public RasterPath realize(Affine a) {
 
@@ -485,6 +546,9 @@ public final class VectorGraphics {
        int[] edges = new int[DEFAULT_PATHLEN];
         int numedges = 0;
 
+        /** translate a rasterized path */
+        public void translate(int dx, int dy) { for(int i=0; i<numvertices; i++) { x[i] += dx; y[i] += dy; } }
+
         /** simple quicksort, from http://sourceforge.net/snippet/detail.php?type=snippet&id=100240 */
         int sort(int left, int right, boolean partition) {
            if (partition) {
@@ -625,6 +689,20 @@ public final class VectorGraphics {
                 } while(pos < segmentLength);
             }
        }
+
+        // FEATURE: make this faster and cache it; also deal with negative coordinates
+        public int boundingBoxWidth() {
+            int ret = 0;
+            for(int i=0; i<numvertices; i++) ret = Math.max(ret, x[i]);
+            return ret;
+        }
+
+        // FEATURE: make this faster and cache it; also deal with negative coordinates
+        public int boundingBoxHeight() {
+            int ret = 0;
+            for(int i=0; i<numvertices; i++) ret = Math.max(ret, y[i]);
+            return ret;
+        }
     }