summaryrefslogtreecommitdiffstats
path: root/tools/layoutlib
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@google.com>2010-01-22 09:45:49 -0800
committerAndroid Git Automerger <android-git-automerger@android.com>2010-01-22 09:45:49 -0800
commit28d9c60ee203eff53a5a8577df8a780402173b24 (patch)
tree0149aa577e65eda2c1050182a56a95f7be227515 /tools/layoutlib
parentb70efcbbb1ae0672c43da86511daf49d177d8ed8 (diff)
parent60e3c09ec0fa73a3e650f4aec89c763599c2e0b7 (diff)
downloadframeworks_base-28d9c60ee203eff53a5a8577df8a780402173b24.zip
frameworks_base-28d9c60ee203eff53a5a8577df8a780402173b24.tar.gz
frameworks_base-28d9c60ee203eff53a5a8577df8a780402173b24.tar.bz2
am 60e3c09e: am 6866daee: Merge "ADT/Layoutlib: implement radial gradient." into eclair
Merge commit '60e3c09ec0fa73a3e650f4aec89c763599c2e0b7' * commit '60e3c09ec0fa73a3e650f4aec89c763599c2e0b7': ADT/Layoutlib: implement radial gradient.
Diffstat (limited to 'tools/layoutlib')
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/GradientShader.java197
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LinearGradient.java202
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/RadialGradient.java158
3 files changed, 338 insertions, 219 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/GradientShader.java b/tools/layoutlib/bridge/src/android/graphics/GradientShader.java
new file mode 100644
index 0000000..40e5df2
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/GradientShader.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+
+/**
+ * Base class for Gradient shader. This is not a standard android class and is just used
+ * as a base class for the re-implemented gradient classes.
+ *
+ * It also provides a base class to handle common code between the different shaders'
+ * implementations of {@link java.awt.Paint}.
+ *
+ * @see LinearGradient
+ * @see RadialGradient
+ * @see SweepGradient
+ */
+public abstract class GradientShader extends Shader {
+
+ protected final int[] mColors;
+ protected final float[] mPositions;
+
+ /**
+ * Creates the base shader and do some basic test on the parameters.
+ *
+ * @param colors The colors to be distributed along the gradient line
+ * @param positions May be null. The relative positions [0..1] of each
+ * corresponding color in the colors array. If this is null, the
+ * the colors are distributed evenly along the gradient line.
+ */
+ protected GradientShader(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");
+ }
+
+ if (positions == null) {
+ float spacing = 1.f / (colors.length - 1);
+ positions = new float[colors.length];
+ positions[0] = 0.f;
+ positions[colors.length-1] = 1.f;
+ for (int i = 1; i < colors.length - 1 ; i++) {
+ positions[i] = spacing * i;
+ }
+ }
+
+ mColors = colors;
+ mPositions = positions;
+ }
+
+ /**
+ * Base class for (Java) Gradient Paints. This handles computing the gradient colors based
+ * on the color and position lists, as well as the {@link TileMode}
+ *
+ */
+ protected abstract static class GradientPaint implements java.awt.Paint {
+ private final static int GRADIENT_SIZE = 100;
+
+ private final int[] mColors;
+ private final float[] mPositions;
+ private final TileMode mTileMode;
+ private int[] mGradient;
+
+ protected GradientPaint(int[] colors, float[] positions, TileMode tileMode) {
+ mColors = colors;
+ mPositions = positions;
+ mTileMode = tileMode;
+ }
+
+ public int getTransparency() {
+ return java.awt.Paint.TRANSLUCENT;
+ }
+
+ /**
+ * Pre-computes the colors for the gradient. This must be called once before any call
+ * to {@link #getGradientColor(float)}
+ */
+ protected synchronized void precomputeGradientColors() {
+ if (mGradient == null) {
+ // actually create an array with an extra size, so that we can really go
+ // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0
+ mGradient = new int[GRADIENT_SIZE+1];
+
+ int prevPos = 0;
+ int nextPos = 1;
+ for (int i = 0 ; i <= GRADIENT_SIZE ; i++) {
+ // compute current position
+ float currentPos = (float)i/GRADIENT_SIZE;
+ while (currentPos > mPositions[nextPos]) {
+ prevPos = nextPos++;
+ }
+
+ float percent = (currentPos - mPositions[prevPos]) /
+ (mPositions[nextPos] - mPositions[prevPos]);
+
+ mGradient[i] = computeColor(mColors[prevPos], mColors[nextPos], percent);
+ }
+ }
+ }
+
+ /**
+ * Returns the color based on the position in the gradient.
+ * <var>pos</var> can be anything, even &lt; 0 or &gt; > 1, as the gradient
+ * will use {@link TileMode} value to convert it into a [0,1] value.
+ */
+ 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;
+ }
+ } 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;
+ }
+ }
+
+ int index = (int)((pos * GRADIENT_SIZE) + .5);
+
+ return mGradient[index];
+ }
+
+ /**
+ * Returns the color between c1, and c2, based on the percent of the distance
+ * between c1 and c2.
+ */
+ private int computeColor(int c1, int c2, float percent) {
+ int a = computeChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent);
+ int r = computeChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent);
+ int g = computeChannel((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF, percent);
+ int b = computeChannel((c1 ) & 0xFF, (c2 ) & 0xFF, percent);
+ return a << 24 | r << 16 | g << 8 | b;
+ }
+
+ /**
+ * Returns the channel value between 2 values based on the percent of the distance between
+ * the 2 values..
+ */
+ private int computeChannel(int c1, int c2, float percent) {
+ return c1 + (int)((percent * (c2-c1)) + .5);
+ }
+
+
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java
index 38ffed3..10c4a5e 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java
@@ -16,19 +16,9 @@
package android.graphics;
-import java.awt.Paint;
-import java.awt.PaintContext;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.Raster;
+public class LinearGradient extends GradientShader {
-public class LinearGradient extends Shader {
-
- private Paint mJavaPaint;
+ private java.awt.Paint mJavaPaint;
/**
* Create a shader that draws a linear gradient along a line.
@@ -45,24 +35,8 @@ public class LinearGradient extends Shader {
*/
public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
TileMode tile) {
- 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");
- }
-
- if (positions == null) {
- float spacing = 1.f / (colors.length - 1);
- positions = new float[colors.length];
- positions[0] = 0.f;
- positions[colors.length-1] = 1.f;
- for (int i = 1; i < colors.length - 1 ; i++) {
- positions[i] = spacing * i;
- }
- }
-
- mJavaPaint = new MultiPointLinearGradientPaint(x0, y0, x1, y1, colors, positions, tile);
+ super(colors, positions);
+ mJavaPaint = new LinearGradientPaint(x0, y0, x1, y1, mColors, mPositions, tile);
}
/**
@@ -84,117 +58,62 @@ public class LinearGradient extends Shader {
// ---------- Custom Methods
@Override
- public Paint getJavaPaint() {
+ java.awt.Paint getJavaPaint() {
return mJavaPaint;
}
- private static class MultiPointLinearGradientPaint implements Paint {
- private final static int GRADIENT_SIZE = 100;
+ /**
+ * Linear Gradient (Java) Paint able to handle more than 2 points, as
+ * {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile
+ * modes.
+ */
+ private static class LinearGradientPaint extends GradientPaint {
private final float mX0;
private final float mY0;
private final float mDx;
private final float mDy;
private final float mDSize2;
- private final int[] mColors;
- private final float[] mPositions;
- private final TileMode mTile;
- private int[] mGradient;
- public MultiPointLinearGradientPaint(float x0, float y0, float x1, float y1, int colors[],
+ public LinearGradientPaint(float x0, float y0, float x1, float y1, int colors[],
float positions[], TileMode tile) {
+ super(colors, positions, tile);
mX0 = x0;
mY0 = y0;
mDx = x1 - x0;
mDy = y1 - y0;
mDSize2 = mDx * mDx + mDy * mDy;
-
- mColors = colors;
- mPositions = positions;
- mTile = tile;
}
- public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
- Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
- prepareColors();
- return new MultiPointLinearGradientPaintContext(cm, deviceBounds,
- userBounds, xform, hints);
+ 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 LinearGradientPaintContext(colorModel);
}
- public int getTransparency() {
- return TRANSLUCENT;
- }
-
- private synchronized void prepareColors() {
- if (mGradient == null) {
- // actually create an array with an extra size, so that we can really go
- // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0
- mGradient = new int[GRADIENT_SIZE+1];
-
- int prevPos = 0;
- int nextPos = 1;
- for (int i = 0 ; i <= GRADIENT_SIZE ; i++) {
- // compute current position
- float currentPos = (float)i/GRADIENT_SIZE;
- while (currentPos > mPositions[nextPos]) {
- prevPos = nextPos++;
- }
-
- float percent = (currentPos - mPositions[prevPos]) /
- (mPositions[nextPos] - mPositions[prevPos]);
+ private class LinearGradientPaintContext implements java.awt.PaintContext {
- mGradient[i] = getColor(mColors[prevPos], mColors[nextPos], percent);
- }
- }
- }
+ private final java.awt.image.ColorModel mColorModel;
- /**
- * Returns the color between c1, and c2, based on the percent of the distance
- * between c1 and c2.
- */
- private int getColor(int c1, int c2, float percent) {
- int a = getChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent);
- int r = getChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent);
- int g = getChannel((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF, percent);
- int b = getChannel((c1 ) & 0xFF, (c2 ) & 0xFF, percent);
- return a << 24 | r << 16 | g << 8 | b;
- }
-
- /**
- * Returns the channel value between 2 values based on the percent of the distance between
- * the 2 values..
- */
- private int getChannel(int c1, int c2, float percent) {
- return c1 + (int)((percent * (c2-c1)) + .5);
- }
-
- private class MultiPointLinearGradientPaintContext implements PaintContext {
-
- private ColorModel mColorModel;
- private final Rectangle mDeviceBounds;
- private final Rectangle2D mUserBounds;
- private final AffineTransform mXform;
- private final RenderingHints mHints;
-
- public MultiPointLinearGradientPaintContext(ColorModel cm, Rectangle deviceBounds,
- Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
- mColorModel = cm;
+ public LinearGradientPaintContext(java.awt.image.ColorModel colorModel) {
+ mColorModel = colorModel;
// FIXME: so far all this is always the same rect gotten in getRaster with an indentity matrix?
- mDeviceBounds = deviceBounds;
- mUserBounds = userBounds;
- mXform = xform;
- mHints = hints;
}
public void dispose() {
}
- public ColorModel getColorModel() {
+ public java.awt.image.ColorModel getColorModel() {
return mColorModel;
}
- public Raster getRaster(int x, int y, int w, int h) {
- BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+ 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];
@@ -236,7 +155,7 @@ public class LinearGradient extends Shader {
private int getColor(float absPos, float refPos, float refSize) {
float pos = (absPos - refPos) / refSize;
- return getIndexFromPos(pos);
+ return getGradientColor(pos);
}
/**
@@ -248,66 +167,7 @@ public class LinearGradient extends Shader {
// from it get the position relative to the vector
float pos = (float) ((_x - mX0) / mDx);
- return getIndexFromPos(pos);
- }
-
- /**
- * Returns the color based on the position in the gradient.
- * <var>pos</var> can be anything, even &lt; 0 or &gt; > 1, as the gradient
- * will use {@link TileMode} value to convert it into a [0,1] value.
- */
- private int getIndexFromPos(float pos) {
- if (pos < 0.f) {
- switch (mTile) {
- 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 if (pos > 1f) {
- switch (mTile) {
- 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;
- }
- }
-
- int index = (int)((pos * GRADIENT_SIZE) + .5);
-
- return mGradient[index];
+ return getGradientColor(pos);
}
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
index 13848c5..db8dff2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
@@ -16,55 +16,117 @@
package android.graphics;
-import java.awt.Paint;
-
-public class RadialGradient extends Shader {
-
- /** Create a shader that draws a radial gradient given the center and radius.
- @param x The x-coordinate of the center of the radius
- @param y The y-coordinate of the center of the radius
- @param radius Must be positive. The radius of the circle for this gradient
- @param colors The colors to be distributed between the center and edge of the circle
- @param positions May be NULL. The relative position of
- each corresponding color in the colors array. If this is NULL,
- the the colors are distributed evenly between the center and edge of the circle.
- @param tile The Shader tiling mode
- */
- public RadialGradient(float x, float y, float radius,
- int colors[], float positions[], TileMode tile) {
- if (radius <= 0) {
- throw new IllegalArgumentException("radius must be > 0");
- }
- 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");
- }
-
- // FIXME Implement shader
- }
-
- /** Create a shader that draws a radial gradient given the center and radius.
- @param x The x-coordinate of the center of the radius
- @param y The y-coordinate of the center of the radius
- @param radius Must be positive. The radius of the circle for this gradient
- @param color0 The color at the center of the circle.
- @param color1 The color at the edge of the circle.
- @param tile The Shader tiling mode
- */
- public RadialGradient(float x, float y, float radius,
- int color0, int color1, TileMode tile) {
- if (radius <= 0) {
- throw new IllegalArgumentException("radius must be > 0");
- }
- // FIXME Implement shader
- }
+public class RadialGradient extends GradientShader {
+
+ private RadialGradientPaint mPaint;
+
+ /**
+ * Create a shader that draws a radial gradient given the center and radius.
+ *
+ * @param x The x-coordinate of the center of the radius
+ * @param y The y-coordinate of the center of the radius
+ * @param radius Must be positive. The radius of the circle for this
+ * gradient
+ * @param colors The colors to be distributed between the center and edge of
+ * the circle
+ * @param positions May be NULL. The relative position of each corresponding
+ * color in the colors array. If this is NULL, the the colors are
+ * distributed evenly between the center and edge of the circle.
+ * @param tile The Shader tiling mode
+ */
+ public RadialGradient(float x, float y, float radius, int colors[], float positions[],
+ TileMode tile) {
+ super(colors, positions);
+ if (radius <= 0) {
+ throw new IllegalArgumentException("radius must be > 0");
+ }
+
+ mPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile);
+ }
+
+ /**
+ * Create a shader that draws a radial gradient given the center and radius.
+ *
+ * @param x The x-coordinate of the center of the radius
+ * @param y The y-coordinate of the center of the radius
+ * @param radius Must be positive. The radius of the circle for this
+ * gradient
+ * @param color0 The color at the center of the circle.
+ * @param color1 The color at the edge of the circle.
+ * @param tile The Shader tiling mode
+ */
+ public RadialGradient(float x, float y, float radius, int color0, int color1, TileMode tile) {
+ this(x, y, radius, new int[] { color0, color1 }, null /* positions */, tile);
+ }
@Override
- Paint getJavaPaint() {
- // TODO Auto-generated method stub
- return null;
+ java.awt.Paint getJavaPaint() {
+ return mPaint;
}
-}
+ private static class RadialGradientPaint extends GradientPaint {
+
+ private final float mX;
+ private final float mY;
+ private final float mRadius;
+
+ public RadialGradientPaint(float x, float y, float radius, int[] colors, float[] positions, TileMode mode) {
+ super(colors, positions, mode);
+ mX = x;
+ mY = y;
+ mRadius = radius;
+ }
+
+ 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 RadialGradientPaintContext(colorModel);
+ }
+
+ private class RadialGradientPaintContext implements java.awt.PaintContext {
+
+ private final java.awt.image.ColorModel mColorModel;
+
+ public RadialGradientPaintContext(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 distance 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 _x = x + ix - mX;
+ float _y = y + iy - mY;
+ float distance = (float) Math.sqrt(_x * _x + _y * _y);
+
+ data[index++] = getGradientColor(distance / mRadius);
+ }
+ }
+
+ image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
+
+ return image.getRaster();
+ }
+
+ }
+ }
+
+}