OSDN Git Service

ADT/Layoutlib: implement sweep gradient.
authorXavier Ducrohet <xav@android.com>
Wed, 20 Jan 2010 02:51:06 +0000 (18:51 -0800)
committerXavier Ducrohet <xav@android.com>
Wed, 20 Jan 2010 02:51:06 +0000 (18:51 -0800)
Change-Id: I2d460decff82f5f64b0a5cfeaa68156aad4fb3e6

tools/layoutlib/bridge/src/android/graphics/GradientShader.java
tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
tools/layoutlib/bridge/src/android/graphics/SweepGradient.java

index 40e5df2..8c5a2a4 100644 (file)
@@ -120,50 +120,58 @@ public abstract class GradientShader extends Shader {
          */
         protected int getGradientColor(float pos) {
             if (pos < 0.f) {
-                switch (mTileMode) {
-                    case CLAMP:
-                        pos = 0.f;
-                        break;
-                    case REPEAT:
-                        // remove the integer part to stay in the [0,1] range
-                        // careful: this is a negative value, so use ceil instead of floor
-                        pos = pos - (float)Math.ceil(pos);
-                        break;
-                    case MIRROR:
-                        // get the integer and the decimal part
-                        // careful: this is a negative value, so use ceil instead of floor
-                        int intPart = (int)Math.ceil(pos);
-                        pos = pos - intPart;
-                        // 0  -> -1 : mirrored order
-                        // -1 -> -2: normal order
-                        // etc..
-                        // this means if the intpart is even we invert
-                        if ((intPart % 2) == 0) {
-                            pos = 1.f - pos;
-                        }
-                        break;
+                if (mTileMode != null) {
+                    switch (mTileMode) {
+                        case CLAMP:
+                            pos = 0.f;
+                            break;
+                        case REPEAT:
+                            // remove the integer part to stay in the [0,1] range
+                            // careful: this is a negative value, so use ceil instead of floor
+                            pos = pos - (float)Math.ceil(pos);
+                            break;
+                        case MIRROR:
+                            // get the integer and the decimal part
+                            // careful: this is a negative value, so use ceil instead of floor
+                            int intPart = (int)Math.ceil(pos);
+                            pos = pos - intPart;
+                            // 0  -> -1 : mirrored order
+                            // -1 -> -2: normal order
+                            // etc..
+                            // this means if the intpart is even we invert
+                            if ((intPart % 2) == 0) {
+                                pos = 1.f - pos;
+                            }
+                            break;
+                    }
+                } else {
+                    pos = 0.0f;
                 }
             } else if (pos > 1f) {
-                switch (mTileMode) {
-                    case CLAMP:
-                        pos = 1.f;
-                        break;
-                    case REPEAT:
-                        // remove the integer part to stay in the [0,1] range
-                        pos = pos - (float)Math.floor(pos);
-                        break;
-                    case MIRROR:
-                        // get the integer and the decimal part
-                        int intPart = (int)Math.floor(pos);
-                        pos = pos - intPart;
-                        // 0 -> 1 : normal order
-                        // 1 -> 2: mirrored
-                        // etc..
-                        // this means if the intpart is odd we invert
-                        if ((intPart % 2) == 1) {
-                            pos = 1.f - pos;
-                        }
-                        break;
+                if (mTileMode != null) {
+                    switch (mTileMode) {
+                        case CLAMP:
+                            pos = 1.f;
+                            break;
+                        case REPEAT:
+                            // remove the integer part to stay in the [0,1] range
+                            pos = pos - (float)Math.floor(pos);
+                            break;
+                        case MIRROR:
+                            // get the integer and the decimal part
+                            int intPart = (int)Math.floor(pos);
+                            pos = pos - intPart;
+                            // 0 -> 1 : normal order
+                            // 1 -> 2: mirrored
+                            // etc..
+                            // this means if the intpart is odd we invert
+                            if ((intPart % 2) == 1) {
+                                pos = 1.f - pos;
+                            }
+                            break;
+                    }
+                } else {
+                    pos = 1.0f;
                 }
             }
 
index db8dff2..4409a80 100644 (file)
@@ -78,11 +78,11 @@ public class RadialGradient extends GradientShader {
         }
 
         public java.awt.PaintContext createContext(
-                java.awt.image.ColorModel colorModel,
-                java.awt.Rectangle deviceBounds,
-                java.awt.geom.Rectangle2D userBounds,
+                java.awt.image.ColorModel     colorModel,
+                java.awt.Rectangle            deviceBounds,
+                java.awt.geom.Rectangle2D     userBounds,
                 java.awt.geom.AffineTransform xform,
-                java.awt.RenderingHints hints) {
+                java.awt.RenderingHints       hints) {
             precomputeGradientColors();
             return new RadialGradientPaintContext(colorModel);
         }
index 21d8244..87036ed 100644 (file)
@@ -16,9 +16,9 @@
 
 package android.graphics;
 
-import java.awt.Paint;
+public class SweepGradient extends GradientShader {
 
-public class SweepGradient extends Shader {
+    private SweepGradientPaint mPaint;
 
     /**
      * A subclass of Shader that draws a sweep gradient around a center point.
@@ -36,15 +36,9 @@ public class SweepGradient extends Shader {
      */
     public SweepGradient(float cx, float cy,
                          int colors[], float positions[]) {
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (positions != null && colors.length != positions.length) {
-            throw new IllegalArgumentException(
-                        "color and position arrays must be of equal length");
-        }
+        super(colors, positions);
 
-        // FIXME Implement shader
+        mPaint = new SweepGradientPaint(cx, cy, mColors, mPositions);
     }
 
     /**
@@ -56,13 +50,91 @@ public class SweepGradient extends Shader {
      * @param color1   The color to use at the end of the sweep
      */
     public SweepGradient(float cx, float cy, int color0, int color1) {
-        // FIXME Implement shader
+        this(cx, cy, new int[] { color0, color1}, null /*positions*/);
     }
 
     @Override
-    Paint getJavaPaint() {
-        // TODO Auto-generated method stub
-        return null;
+    java.awt.Paint getJavaPaint() {
+        return mPaint;
     }
+
+    private static class SweepGradientPaint extends GradientPaint {
+
+        private final float mCx;
+        private final float mCy;
+
+        public SweepGradientPaint(float cx, float cy, int[] colors, float[] positions) {
+            super(colors, positions, null /*tileMode*/);
+            mCx = cx;
+            mCy = cy;
+        }
+
+        public java.awt.PaintContext createContext(
+                java.awt.image.ColorModel     colorModel,
+                java.awt.Rectangle            deviceBounds,
+                java.awt.geom.Rectangle2D     userBounds,
+                java.awt.geom.AffineTransform xform,
+                java.awt.RenderingHints       hints) {
+            precomputeGradientColors();
+            return new SweepGradientPaintContext(colorModel);
+        }
+
+        private class SweepGradientPaintContext implements java.awt.PaintContext {
+
+            private final java.awt.image.ColorModel mColorModel;
+
+            public SweepGradientPaintContext(java.awt.image.ColorModel colorModel) {
+                mColorModel = colorModel;
+            }
+
+            public void dispose() {
+            }
+
+            public java.awt.image.ColorModel getColorModel() {
+                return mColorModel;
+            }
+
+            public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
+                java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h,
+                        java.awt.image.BufferedImage.TYPE_INT_ARGB);
+
+                int[] data = new int[w*h];
+
+                // compute angle from each point to the center, and figure out the distance from
+                // it.
+                int index = 0;
+                for (int iy = 0 ; iy < h ; iy++) {
+                    for (int ix = 0 ; ix < w ; ix++) {
+                        float dx = x + ix - mCx;
+                        float dy = y + iy - mCy;
+                        float angle;
+                        if (dx == 0) {
+                            angle = (float) (dy < 0 ? 3 * Math.PI / 2 : Math.PI / 2);
+                        } else if (dy == 0) {
+                            angle = (float) (dx < 0 ? Math.PI : 0);
+                        } else {
+                            angle = (float) Math.atan(dy / dx);
+                            if (dx > 0) {
+                                if (dy < 0) {
+                                    angle += Math.PI * 2;
+                                }
+                            } else {
+                                angle += Math.PI;
+                            }
+                        }
+
+                        // convert to 0-1. value and get color
+                        data[index++] = getGradientColor((float) (angle / (2 * Math.PI)));
+                    }
+                }
+
+                image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
+
+                return image.getRaster();
+            }
+
+        }
+    }
+
 }