summaryrefslogtreecommitdiffstats
path: root/graphics/java
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/java')
-rw-r--r--graphics/java/android/graphics/Bitmap.java232
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java2
-rw-r--r--graphics/java/android/graphics/BitmapRegionDecoder.java37
-rw-r--r--graphics/java/android/graphics/Paint.java22
-rw-r--r--graphics/java/android/graphics/Rect.java12
-rw-r--r--graphics/java/android/graphics/RectF.java24
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java9
-rw-r--r--graphics/java/android/graphics/drawable/ColorDrawable.java20
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java46
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java23
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java87
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java13
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java12
-rw-r--r--graphics/java/android/graphics/drawable/StateListDrawable.java10
-rw-r--r--graphics/java/android/renderscript/Matrix2f.java20
-rw-r--r--graphics/java/android/renderscript/Matrix3f.java20
-rw-r--r--graphics/java/android/renderscript/Matrix4f.java48
-rw-r--r--graphics/java/android/renderscript/RenderScript.java42
-rw-r--r--graphics/java/android/renderscript/Script.java95
-rw-r--r--graphics/java/android/renderscript/ScriptGroup.java464
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsic.java36
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicBlend.java465
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicBlur.java112
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java167
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java125
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java119
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicLUT.java146
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java89
31 files changed, 2367 insertions, 138 deletions
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c726d0e..688fd7a 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -27,7 +27,6 @@ import java.nio.IntBuffer;
import java.nio.ShortBuffer;
public final class Bitmap implements Parcelable {
-
/**
* Indicates that the bitmap was created for an unknown pixel density.
*
@@ -64,7 +63,7 @@ public final class Bitmap implements Parcelable {
private boolean mRecycled;
// Package-scoped for fast access.
- /*package*/ int mDensity = sDefaultDensity = getDefaultDensity();
+ int mDensity = getDefaultDensity();
private static volatile Matrix sScaleMatrix;
@@ -78,15 +77,15 @@ public final class Bitmap implements Parcelable {
public static void setDefaultDensity(int density) {
sDefaultDensity = density;
}
-
- /*package*/ static int getDefaultDensity() {
+
+ static int getDefaultDensity() {
if (sDefaultDensity >= 0) {
return sDefaultDensity;
}
sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
return sDefaultDensity;
}
-
+
/**
* @noinspection UnusedDeclaration
*/
@@ -95,7 +94,7 @@ public final class Bitmap implements Parcelable {
This can be called from JNI code.
*/
- /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
int density) {
this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
}
@@ -108,7 +107,7 @@ public final class Bitmap implements Parcelable {
This can be called from JNI code.
*/
- /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
int[] layoutBounds, int density) {
if (nativeBitmap == 0) {
throw new RuntimeException("internal error: native bitmap is 0");
@@ -202,9 +201,14 @@ public final class Bitmap implements Parcelable {
*/
public void recycle() {
if (!mRecycled) {
- mBuffer = null;
- nativeRecycle(mNativeBitmap);
- mNinePatchChunk = null;
+ if (nativeRecycle(mNativeBitmap)) {
+ // return value indicates whether native pixel object was actually recycled.
+ // false indicates that it is still in use at the native level and these
+ // objects should not be collected now. They will be collected later when the
+ // Bitmap itself is collected.
+ mBuffer = null;
+ mNinePatchChunk = null;
+ }
mRecycled = true;
}
}
@@ -347,11 +351,15 @@ public final class Bitmap implements Parcelable {
}
/**
- * Copy the bitmap's pixels into the specified buffer (allocated by the
+ * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
* caller). An exception is thrown if the buffer is not large enough to
* hold all of the pixels (taking into account the number of bytes per
* pixel) or if the Buffer subclass is not one of the support types
- * (ByteBuffer, ShortBuffer, IntBuffer).
+ * (ByteBuffer, ShortBuffer, IntBuffer).</p>
+ * <p>The content of the bitmap is copied into the buffer as-is. This means
+ * that if this bitmap stores its pixels pre-multiplied
+ * (see {@link #isPremultiplied()}, the values in the buffer will also be
+ * pre-multiplied.</p>
*/
public void copyPixelsToBuffer(Buffer dst) {
int elements = dst.remaining();
@@ -382,10 +390,10 @@ public final class Bitmap implements Parcelable {
}
/**
- * Copy the pixels from the buffer, beginning at the current position,
+ * <p>Copy the pixels from the buffer, beginning at the current position,
* overwriting the bitmap's pixels. The data in the buffer is not changed
* in any way (unlike setPixels(), which converts from unpremultipled 32bit
- * to whatever the bitmap's native format is.
+ * to whatever the bitmap's native format is.</p>
*/
public void copyPixelsFromBuffer(Buffer src) {
checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
@@ -402,7 +410,7 @@ public final class Bitmap implements Parcelable {
throw new RuntimeException("unsupported Buffer subclass");
}
- long bufferBytes = (long)elements << shift;
+ long bufferBytes = (long) elements << shift;
long bitmapBytes = getByteCount();
if (bufferBytes < bitmapBytes) {
@@ -410,6 +418,11 @@ public final class Bitmap implements Parcelable {
}
nativeCopyPixelsFromBuffer(mNativeBitmap, src);
+
+ // now update the buffer's position
+ int position = src.position();
+ position += bitmapBytes >> shift;
+ src.position(position);
}
/**
@@ -622,6 +635,22 @@ public final class Bitmap implements Parcelable {
/**
* Returns a mutable bitmap with the specified width and height. Its
+ * initial density is determined from the given {@link DisplayMetrics}.
+ *
+ * @param display Display metrics for the display this bitmap will be
+ * drawn on.
+ * @param width The width of the bitmap
+ * @param height The height of the bitmap
+ * @param config The bitmap config to create.
+ * @throws IllegalArgumentException if the width or height are <= 0
+ */
+ public static Bitmap createBitmap(DisplayMetrics display, int width,
+ int height, Config config) {
+ return createBitmap(display, width, height, config, true);
+ }
+
+ /**
+ * Returns a mutable bitmap with the specified width and height. Its
* initial density is as per {@link #getDensity}.
*
* @param width The width of the bitmap
@@ -634,10 +663,33 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0
*/
private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
+ return createBitmap(null, width, height, config, hasAlpha);
+ }
+
+ /**
+ * Returns a mutable bitmap with the specified width and height. Its
+ * initial density is determined from the given {@link DisplayMetrics}.
+ *
+ * @param display Display metrics for the display this bitmap will be
+ * drawn on.
+ * @param width The width of the bitmap
+ * @param height The height of the bitmap
+ * @param config The bitmap config to create.
+ * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
+ * bitmap as opaque. Doing so will clear the bitmap in black
+ * instead of transparent.
+ *
+ * @throws IllegalArgumentException if the width or height are <= 0
+ */
+ private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
+ Config config, boolean hasAlpha) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
+ if (display != null) {
+ bm.mDensity = display.densityDpi;
+ }
if (config == Config.ARGB_8888 && !hasAlpha) {
nativeErase(bm.mNativeBitmap, 0xff000000);
nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha);
@@ -670,6 +722,31 @@ public final class Bitmap implements Parcelable {
*/
public static Bitmap createBitmap(int colors[], int offset, int stride,
int width, int height, Config config) {
+ return createBitmap(null, colors, offset, stride, width, height, config);
+ }
+
+ /**
+ * Returns a immutable bitmap with the specified width and height, with each
+ * pixel value set to the corresponding value in the colors array. Its
+ * initial density is determined from the given {@link DisplayMetrics}.
+ *
+ * @param display Display metrics for the display this bitmap will be
+ * drawn on.
+ * @param colors Array of {@link Color} used to initialize the pixels.
+ * @param offset Number of values to skip before the first color in the
+ * array of colors.
+ * @param stride Number of colors in the array between rows (must be >=
+ * width or <= -width).
+ * @param width The width of the bitmap
+ * @param height The height of the bitmap
+ * @param config The bitmap config to create. If the config does not
+ * support per-pixel alpha (e.g. RGB_565), then the alpha
+ * bytes in the colors[] will be ignored (assumed to be FF)
+ * @throws IllegalArgumentException if the width or height are <= 0, or if
+ * the color array's length is less than the number of pixels.
+ */
+ public static Bitmap createBitmap(DisplayMetrics display, int colors[],
+ int offset, int stride, int width, int height, Config config) {
checkWidthHeight(width, height);
if (Math.abs(stride) < width) {
@@ -684,8 +761,12 @@ public final class Bitmap implements Parcelable {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
- return nativeCreate(colors, offset, stride, width, height,
+ Bitmap bm = nativeCreate(colors, offset, stride, width, height,
config.nativeInt, false);
+ if (display != null) {
+ bm.mDensity = display.densityDpi;
+ }
+ return bm;
}
/**
@@ -704,7 +785,29 @@ public final class Bitmap implements Parcelable {
* the color array's length is less than the number of pixels.
*/
public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
- return createBitmap(colors, 0, width, width, height, config);
+ return createBitmap(null, colors, 0, width, width, height, config);
+ }
+
+ /**
+ * Returns a immutable bitmap with the specified width and height, with each
+ * pixel value set to the corresponding value in the colors array. Its
+ * initial density is determined from the given {@link DisplayMetrics}.
+ *
+ * @param display Display metrics for the display this bitmap will be
+ * drawn on.
+ * @param colors Array of {@link Color} used to initialize the pixels.
+ * This array must be at least as large as width * height.
+ * @param width The width of the bitmap
+ * @param height The height of the bitmap
+ * @param config The bitmap config to create. If the config does not
+ * support per-pixel alpha (e.g. RGB_565), then the alpha
+ * bytes in the colors[] will be ignored (assumed to be FF)
+ * @throws IllegalArgumentException if the width or height are <= 0, or if
+ * the color array's length is less than the number of pixels.
+ */
+ public static Bitmap createBitmap(DisplayMetrics display, int colors[],
+ int width, int height, Config config) {
+ return createBitmap(display, colors, 0, width, width, height, config);
}
/**
@@ -780,6 +883,27 @@ public final class Bitmap implements Parcelable {
return mIsMutable;
}
+ /**
+ * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
+ * When a pixel is pre-multiplied, the RGB components have been multiplied by
+ * the alpha component. For instance, if the original color is a 50%
+ * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
+ * <code>(128, 128, 0, 0)</code>.</p>
+ *
+ * <p>This method always returns false if {@link #getConfig()} is
+ * {@link Bitmap.Config#RGB_565}.</p>
+ *
+ * <p>This method only returns true if {@link #hasAlpha()} returns true.
+ * A bitmap with no alpha channel can be used both as a pre-multiplied and
+ * as a non pre-multiplied bitmap.</p>
+ *
+ * @return true if the underlying pixels have been pre-multiplied, false
+ * otherwise
+ */
+ public final boolean isPremultiplied() {
+ return getConfig() != Config.RGB_565 && hasAlpha();
+ }
+
/** Returns the bitmap's width */
public final int getWidth() {
return mWidth == -1 ? mWidth = nativeWidth(mNativeBitmap) : mWidth;
@@ -848,7 +972,7 @@ public final class Bitmap implements Parcelable {
* @hide
*/
static public int scaleFromDensity(int size, int sdensity, int tdensity) {
- if (sdensity == DENSITY_NONE || sdensity == tdensity) {
+ if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
return size;
}
@@ -911,6 +1035,51 @@ public final class Bitmap implements Parcelable {
}
/**
+ * Indicates whether the renderer responsible for drawing this
+ * bitmap should attempt to use mipmaps when this bitmap is drawn
+ * scaled down.
+ *
+ * If you know that you are going to draw this bitmap at less than
+ * 50% of its original size, you may be able to obtain a higher
+ * quality
+ *
+ * This property is only a suggestion that can be ignored by the
+ * renderer. It is not guaranteed to have any effect.
+ *
+ * @return true if the renderer should attempt to use mipmaps,
+ * false otherwise
+ *
+ * @see #setHasMipMap(boolean)
+ */
+ public final boolean hasMipMap() {
+ return nativeHasMipMap(mNativeBitmap);
+ }
+
+ /**
+ * Set a hint for the renderer responsible for drawing this bitmap
+ * indicating that it should attempt to use mipmaps when this bitmap
+ * is drawn scaled down.
+ *
+ * If you know that you are going to draw this bitmap at less than
+ * 50% of its original size, you may be able to obtain a higher
+ * quality by turning this property on.
+ *
+ * Note that if the renderer respects this hint it might have to
+ * allocate extra memory to hold the mipmap levels for this bitmap.
+ *
+ * This property is only a suggestion that can be ignored by the
+ * renderer. It is not guaranteed to have any effect.
+ *
+ * @param hasMipMap indicates whether the renderer should attempt
+ * to use mipmaps
+ *
+ * @see #hasMipMap()
+ */
+ public final void setHasMipMap(boolean hasMipMap) {
+ nativeSetHasMipMap(mNativeBitmap, hasMipMap);
+ }
+
+ /**
* Fills the bitmap's pixels with the specified {@link Color}.
*
* @throws IllegalStateException if the bitmap is not mutable.
@@ -926,7 +1095,7 @@ public final class Bitmap implements Parcelable {
/**
* Returns the {@link Color} at the specified location. Throws an exception
* if x or y are out of bounds (negative or >= to the width or height
- * respectively).
+ * respectively). The returned color is a non-premultiplied ARGB value.
*
* @param x The x coordinate (0...width-1) of the pixel to return
* @param y The y coordinate (0...height-1) of the pixel to return
@@ -944,6 +1113,7 @@ public final class Bitmap implements Parcelable {
* a packed int representing a {@link Color}. The stride parameter allows
* the caller to allow for gaps in the returned pixels array between
* rows. For normal packed results, just pass width for the stride value.
+ * The returned colors are non-premultiplied ARGB values.
*
* @param pixels The array to receive the bitmap's colors
* @param offset The first index to write into pixels[]
@@ -955,6 +1125,7 @@ public final class Bitmap implements Parcelable {
* the bitmap
* @param width The number of pixels to read from each row
* @param height The number of rows to read
+ *
* @throws IllegalArgumentException if x, y, width, height exceed the
* bounds of the bitmap, or if abs(stride) < width.
* @throws ArrayIndexOutOfBoundsException if the pixels array is too small
@@ -974,6 +1145,7 @@ public final class Bitmap implements Parcelable {
/**
* Shared code to check for illegal arguments passed to getPixel()
* or setPixel()
+ *
* @param x x coordinate of the pixel
* @param y y coordinate of the pixel
*/
@@ -1029,12 +1201,14 @@ public final class Bitmap implements Parcelable {
}
/**
- * Write the specified {@link Color} into the bitmap (assuming it is
- * mutable) at the x,y coordinate.
+ * <p>Write the specified {@link Color} into the bitmap (assuming it is
+ * mutable) at the x,y coordinate. The color must be a
+ * non-premultiplied ARGB value.</p>
*
* @param x The x coordinate of the pixel to replace (0...width-1)
* @param y The y coordinate of the pixel to replace (0...height-1)
- * @param color The {@link Color} to write into the bitmap
+ * @param color The ARGB color to write into the bitmap
+ *
* @throws IllegalStateException if the bitmap is not mutable
* @throws IllegalArgumentException if x, y are outside of the bitmap's
* bounds.
@@ -1049,8 +1223,9 @@ public final class Bitmap implements Parcelable {
}
/**
- * Replace pixels in the bitmap with the colors in the array. Each element
- * in the array is a packed int prepresenting a {@link Color}
+ * <p>Replace pixels in the bitmap with the colors in the array. Each element
+ * in the array is a packed int prepresenting a non-premultiplied ARGB
+ * {@link Color}.</p>
*
* @param pixels The colors to write to the bitmap
* @param offset The index of the first color to read from pixels[]
@@ -1063,6 +1238,7 @@ public final class Bitmap implements Parcelable {
* the bitmap.
* @param width The number of colors to copy from pixels[] per row
* @param height The number of rows to write to the bitmap
+ *
* @throws IllegalStateException if the bitmap is not mutable
* @throws IllegalArgumentException if x, y, width, height are outside of
* the bitmap's bounds.
@@ -1070,7 +1246,7 @@ public final class Bitmap implements Parcelable {
* to receive the specified number of pixels.
*/
public void setPixels(int[] pixels, int offset, int stride,
- int x, int y, int width, int height) {
+ int x, int y, int width, int height) {
checkRecycled("Can't call setPixels() on a recycled bitmap");
if (!isMutable()) {
throw new IllegalStateException();
@@ -1220,7 +1396,7 @@ public final class Bitmap implements Parcelable {
private static native Bitmap nativeCopy(int srcBitmap, int nativeConfig,
boolean isMutable);
private static native void nativeDestructor(int nativeBitmap);
- private static native void nativeRecycle(int nativeBitmap);
+ private static native boolean nativeRecycle(int nativeBitmap);
private static native boolean nativeCompress(int nativeBitmap, int format,
int quality, OutputStream stream,
@@ -1230,7 +1406,6 @@ public final class Bitmap implements Parcelable {
private static native int nativeHeight(int nativeBitmap);
private static native int nativeRowBytes(int nativeBitmap);
private static native int nativeConfig(int nativeBitmap);
- private static native boolean nativeHasAlpha(int nativeBitmap);
private static native int nativeGetPixel(int nativeBitmap, int x, int y);
private static native void nativeGetPixels(int nativeBitmap, int[] pixels,
@@ -1259,7 +1434,10 @@ public final class Bitmap implements Parcelable {
int[] offsetXY);
private static native void nativePrepareToDraw(int nativeBitmap);
+ private static native boolean nativeHasAlpha(int nativeBitmap);
private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha);
+ private static native boolean nativeHasMipMap(int nativeBitmap);
+ private static native void nativeSetHasMipMap(int nBitmap, boolean hasMipMap);
private static native boolean nativeSameAs(int nb0, int nb1);
/* package */ final int ni() {
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 5094df18..381e65b 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -19,6 +19,7 @@ package android.graphics;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.TypedValue;
import java.io.BufferedInputStream;
@@ -303,6 +304,7 @@ public class BitmapFactory {
/* do nothing.
If the exception happened on open, bm will be null.
*/
+ Log.e("BitmapFactory", "Unable to decode stream: " + e);
} finally {
if (stream != null) {
try {
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index c1d3407..b38d107 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -36,6 +36,9 @@ import java.io.InputStream;
public final class BitmapRegionDecoder {
private int mNativeBitmapRegionDecoder;
private boolean mRecycled;
+ // ensures that the native decoder object exists and that only one decode can
+ // occur at a time.
+ private final Object mNativeLock = new Object();
/**
* Create a BitmapRegionDecoder from the specified byte array.
@@ -179,24 +182,30 @@ public final class BitmapRegionDecoder {
* decoded.
*/
public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
- checkRecycled("decodeRegion called on recycled region decoder");
- if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
- || rect.top >= getHeight())
- throw new IllegalArgumentException("rectangle is outside the image");
- return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top, options);
+ synchronized (mNativeLock) {
+ checkRecycled("decodeRegion called on recycled region decoder");
+ if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
+ || rect.top >= getHeight())
+ throw new IllegalArgumentException("rectangle is outside the image");
+ return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top, options);
+ }
}
/** Returns the original image's width */
public int getWidth() {
- checkRecycled("getWidth called on recycled region decoder");
- return nativeGetWidth(mNativeBitmapRegionDecoder);
+ synchronized (mNativeLock) {
+ checkRecycled("getWidth called on recycled region decoder");
+ return nativeGetWidth(mNativeBitmapRegionDecoder);
+ }
}
/** Returns the original image's height */
public int getHeight() {
- checkRecycled("getHeight called on recycled region decoder");
- return nativeGetHeight(mNativeBitmapRegionDecoder);
+ synchronized (mNativeLock) {
+ checkRecycled("getHeight called on recycled region decoder");
+ return nativeGetHeight(mNativeBitmapRegionDecoder);
+ }
}
/**
@@ -210,9 +219,11 @@ public final class BitmapRegionDecoder {
* memory when there are no more references to this region decoder.
*/
public void recycle() {
- if (!mRecycled) {
- nativeClean(mNativeBitmapRegionDecoder);
- mRecycled = true;
+ synchronized (mNativeLock) {
+ if (!mRecycled) {
+ nativeClean(mNativeBitmapRegionDecoder);
+ mRecycled = true;
+ }
}
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f9b8a5f..4170cfe 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -371,12 +371,30 @@ public class Paint {
public void reset() {
native_reset(mNativePaint);
setFlags(DEFAULT_PAINT_FLAGS);
+
// TODO: Turning off hinting has undesirable side effects, we need to
// revisit hinting once we add support for subpixel positioning
// setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
// ? HINTING_OFF : HINTING_ON);
+
+ mColorFilter = null;
+ mMaskFilter = null;
+ mPathEffect = null;
+ mRasterizer = null;
+ mShader = null;
+ mTypeface = null;
+ mXfermode = null;
+
mHasCompatScaling = false;
- mCompatScaling = mInvCompatScaling = 1;
+ mCompatScaling = 1;
+ mInvCompatScaling = 1;
+
+ hasShadow = false;
+ shadowDx = 0;
+ shadowDy = 0;
+ shadowRadius = 0;
+ shadowColor = 0;
+
mBidiFlags = BIDI_DEFAULT_LTR;
setTextLocale(Locale.getDefault());
}
@@ -1055,7 +1073,6 @@ public class Paint {
* Get the text Locale.
*
* @return the paint's Locale used for drawing text, never null.
- * @hide
*/
public Locale getTextLocale() {
return mLocale;
@@ -1086,7 +1103,6 @@ public class Paint {
* job in certain ambiguous cases
*
* @param locale the paint's locale value for drawing text, must not be null.
- * @hide
*/
public void setTextLocale(Locale locale) {
if (locale == null) {
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 6c204ab..8b5609f 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -69,10 +69,14 @@ public final class Rect implements Parcelable {
* rectangle.
*/
public Rect(Rect r) {
- left = r.left;
- top = r.top;
- right = r.right;
- bottom = r.bottom;
+ if (r == null) {
+ left = top = right = bottom = 0;
+ } else {
+ left = r.left;
+ top = r.top;
+ right = r.right;
+ bottom = r.bottom;
+ }
}
@Override
diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java
index 108b7f9..53178b0 100644
--- a/graphics/java/android/graphics/RectF.java
+++ b/graphics/java/android/graphics/RectF.java
@@ -66,17 +66,25 @@ public class RectF implements Parcelable {
* rectangle.
*/
public RectF(RectF r) {
- left = r.left;
- top = r.top;
- right = r.right;
- bottom = r.bottom;
+ if (r == null) {
+ left = top = right = bottom = 0.0f;
+ } else {
+ left = r.left;
+ top = r.top;
+ right = r.right;
+ bottom = r.bottom;
+ }
}
public RectF(Rect r) {
- left = r.left;
- top = r.top;
- right = r.right;
- bottom = r.bottom;
+ if (r == null) {
+ left = top = right = bottom = 0.0f;
+ } else {
+ left = r.left;
+ top = r.top;
+ right = r.right;
+ bottom = r.bottom;
+ }
}
@Override
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 87421b1..e82ccd4 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -385,7 +385,7 @@ public class BitmapDrawable extends Drawable {
Shader shader = state.mPaint.getShader();
if (shader == null) {
if (mApplyGravity) {
- final int layoutDirection = getResolvedLayoutDirectionSelf();
+ final int layoutDirection = getLayoutDirection();
Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
getBounds(), mDstRect, layoutDirection);
mApplyGravity = false;
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index c41dd07..b7429d4 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -209,7 +209,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
if ((mClipState.mOrientation & VERTICAL) != 0) {
h -= (h - ih) * (10000 - level) / 10000;
}
- final int layoutDirection = getResolvedLayoutDirectionSelf();
+ final int layoutDirection = getLayoutDirection();
Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
@@ -239,7 +239,12 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
return null;
}
-
+ /** @hide */
+ @Override
+ public void setLayoutDirection(int layoutDirection) {
+ mClipState.mDrawable.setLayoutDirection(layoutDirection);
+ super.setLayoutDirection(layoutDirection);
+ }
final static class ClipState extends ConstantState {
Drawable mDrawable;
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 88c9155..d11e554 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -20,6 +20,7 @@ import android.graphics.*;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import android.view.ViewDebug;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -34,8 +35,10 @@ import java.io.IOException;
* @attr ref android.R.styleable#ColorDrawable_color
*/
public class ColorDrawable extends Drawable {
+ @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_")
private ColorState mState;
private final Paint mPaint = new Paint();
+ private boolean mMutated;
/**
* Creates a new black ColorDrawable.
@@ -63,6 +66,21 @@ public class ColorDrawable extends Drawable {
return super.getChangingConfigurations() | mState.mChangingConfigurations;
}
+ /**
+ * A mutable BitmapDrawable still shares its Bitmap with any other Drawable
+ * that comes from the same resource.
+ *
+ * @return This drawable.
+ */
+ @Override
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mState = new ColorState(mState);
+ mMutated = true;
+ }
+ return this;
+ }
+
@Override
public void draw(Canvas canvas) {
if ((mState.mUseColor >>> 24) != 0) {
@@ -158,6 +176,7 @@ public class ColorDrawable extends Drawable {
final static class ColorState extends ConstantState {
int mBaseColor; // base color, independent of setAlpha()
+ @ViewDebug.ExportedProperty
int mUseColor; // basecolor modulated by setAlpha()
int mChangingConfigurations;
@@ -165,6 +184,7 @@ public class ColorDrawable extends Drawable {
if (state != null) {
mBaseColor = state.mBaseColor;
mUseColor = state.mUseColor;
+ mChangingConfigurations = state.mChangingConfigurations;
}
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 785582c..f9392e4 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -37,7 +37,6 @@ import android.util.DisplayMetrics;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
-import android.view.View;
import java.io.IOException;
import java.io.InputStream;
@@ -124,6 +123,8 @@ public abstract class Drawable {
private WeakReference<Callback> mCallback = null;
private boolean mVisible = true;
+ private int mLayoutDirection;
+
/**
* Draw in its bounds (set via setBounds) respecting optional effects such
* as alpha (set via setAlpha) and color filter (set via setColorFilter).
@@ -296,19 +297,6 @@ public abstract class Drawable {
}
/**
- * Implement this interface if you want to create an drawable that is RTL aware
- * @hide
- */
- public static interface Callback2 extends Callback {
- /**
- * A Drawable can call this to get the resolved layout direction of the <var>who</var>.
- *
- * @param who The drawable being queried.
- */
- public int getResolvedLayoutDirection(Drawable who);
- }
-
- /**
* Bind a {@link Callback} object to this Drawable. Required for clients
* that want to support animated drawables.
*
@@ -385,15 +373,30 @@ public abstract class Drawable {
}
/**
- * Get the resolved layout direction of this Drawable.
+ * Returns the resolved layout direction for this Drawable.
+ *
+ * @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
+ * {@link android.view.View#LAYOUT_DIRECTION_RTL}
+ *
* @hide
*/
- public int getResolvedLayoutDirectionSelf() {
- final Callback callback = getCallback();
- if (callback == null || !(callback instanceof Callback2)) {
- return View.LAYOUT_DIRECTION_LTR;
+ public int getLayoutDirection() {
+ return mLayoutDirection;
+ }
+
+ /**
+ * Set the layout direction for this drawable. Should be a resolved direction as the
+ * Drawable as no capacity to do the resolution on his own.
+ *
+ * @param layoutDirection One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
+ * {@link android.view.View#LAYOUT_DIRECTION_RTL}
+ *
+ * @hide
+ */
+ public void setLayoutDirection(int layoutDirection) {
+ if (getLayoutDirection() != layoutDirection) {
+ mLayoutDirection = layoutDirection;
}
- return ((Callback2) callback).getResolvedLayoutDirection(this);
}
/**
@@ -777,7 +780,8 @@ public abstract class Drawable {
// to the compatibility density only to have them scaled back up when
// drawn to the screen.
if (opts == null) opts = new BitmapFactory.Options();
- opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+ opts.inScreenDensity = res != null
+ ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
if (bm != null) {
byte[] np = bm.getNinePatchChunk();
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 15b2c0b..41b272d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -105,7 +105,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mAlpha = alpha;
if (mCurrDrawable != null) {
if (mEnterAnimationEnd == 0) {
- mCurrDrawable.setAlpha(alpha);
+ mCurrDrawable.mutate().setAlpha(alpha);
} else {
animate(false);
}
@@ -118,7 +118,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
if (mDrawableContainerState.mDither != dither) {
mDrawableContainerState.mDither = dither;
if (mCurrDrawable != null) {
- mCurrDrawable.setDither(mDrawableContainerState.mDither);
+ mCurrDrawable.mutate().setDither(mDrawableContainerState.mDither);
}
}
}
@@ -128,7 +128,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
if (mColorFilter != cf) {
mColorFilter = cf;
if (mCurrDrawable != null) {
- mCurrDrawable.setColorFilter(cf);
+ mCurrDrawable.mutate().setColorFilter(cf);
}
}
}
@@ -176,7 +176,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
}
if (mCurrDrawable != null) {
mCurrDrawable.jumpToCurrentState();
- mCurrDrawable.setAlpha(mAlpha);
+ mCurrDrawable.mutate().setAlpha(mAlpha);
}
if (mExitAnimationEnd != 0) {
mExitAnimationEnd = 0;
@@ -312,6 +312,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mCurrDrawable = d;
mCurIndex = idx;
if (d != null) {
+ d.mutate();
if (mDrawableContainerState.mEnterFadeDuration > 0) {
mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
} else {
@@ -355,13 +356,13 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
if (mCurrDrawable != null) {
if (mEnterAnimationEnd != 0) {
if (mEnterAnimationEnd <= now) {
- mCurrDrawable.setAlpha(mAlpha);
+ mCurrDrawable.mutate().setAlpha(mAlpha);
mEnterAnimationEnd = 0;
} else {
int animAlpha = (int)((mEnterAnimationEnd-now)*255)
/ mDrawableContainerState.mEnterFadeDuration;
if (DEBUG) android.util.Log.i(TAG, toString() + " cur alpha " + animAlpha);
- mCurrDrawable.setAlpha(((255-animAlpha)*mAlpha)/255);
+ mCurrDrawable.mutate().setAlpha(((255-animAlpha)*mAlpha)/255);
animating = true;
}
}
@@ -378,7 +379,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
int animAlpha = (int)((mExitAnimationEnd-now)*255)
/ mDrawableContainerState.mExitFadeDuration;
if (DEBUG) android.util.Log.i(TAG, toString() + " last alpha " + animAlpha);
- mLastDrawable.setAlpha((animAlpha*mAlpha)/255);
+ mLastDrawable.mutate().setAlpha((animAlpha*mAlpha)/255);
animating = true;
}
}
@@ -443,7 +444,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
int mConstantMinimumWidth;
int mConstantMinimumHeight;
- boolean mHaveOpacity = false;
int mOpacity;
boolean mHaveStateful = false;
@@ -492,7 +492,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mConstantWidth = orig.mConstantWidth;
mConstantHeight = orig.mConstantHeight;
- mHaveOpacity = orig.mHaveOpacity;
mOpacity = orig.mOpacity;
mHaveStateful = orig.mHaveStateful;
mStateful = orig.mStateful;
@@ -527,7 +526,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mDrawables[pos] = dr;
mNumChildren++;
mChildrenChangingConfigurations |= dr.getChangingConfigurations();
- mHaveOpacity = false;
mHaveStateful = false;
mConstantPadding = null;
@@ -655,10 +653,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
}
public final int getOpacity() {
- if (mHaveOpacity) {
- return mOpacity;
- }
-
final int N = getChildCount();
final Drawable[] drawables = mDrawables;
int op = N > 0 ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
@@ -666,7 +660,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
}
mOpacity = op;
- mHaveOpacity = true;
return op;
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 5b50beb..0623a9e 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -435,7 +435,8 @@ public class GradientDrawable extends Drawable {
final int currFillAlpha = modulateAlpha(prevFillAlpha);
final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
- final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint.getStrokeWidth() > 0;
+ final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
+ mStrokePaint.getStrokeWidth() > 0;
final boolean haveFill = currFillAlpha > 0;
final GradientState st = mGradientState;
/* we need a layer iff we're drawing both a fill and stroke, and the
@@ -477,6 +478,9 @@ public class GradientDrawable extends Drawable {
mFillPaint.setAlpha(currFillAlpha);
mFillPaint.setDither(mDither);
mFillPaint.setColorFilter(mColorFilter);
+ if (mColorFilter != null && !mGradientState.mHasSolidColor) {
+ mFillPaint.setColor(0xff000000);
+ }
if (haveStroke) {
mStrokePaint.setAlpha(currStrokeAlpha);
mStrokePaint.setDither(mDither);
@@ -512,7 +516,10 @@ public class GradientDrawable extends Drawable {
canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
}
} else {
- canvas.drawRect(mRect, mFillPaint);
+ if (mFillPaint.getColor() != 0 || mColorFilter != null ||
+ mFillPaint.getShader() != null) {
+ canvas.drawRect(mRect, mFillPaint);
+ }
if (haveStroke) {
canvas.drawRect(mRect, mStrokePaint);
}
@@ -603,9 +610,9 @@ public class GradientDrawable extends Drawable {
/**
* <p>Changes this drawbale to use a single color instead of a gradient.</p>
- * <p><strong>Note</strong>: changing orientation will affect all instances
+ * <p><strong>Note</strong>: changing color will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
- * {@link #mutate()} before changing the orientation.</p>
+ * {@link #mutate()} before changing the color.</p>
*
* @param argb The color used to fill the shape
*
@@ -649,7 +656,7 @@ public class GradientDrawable extends Drawable {
@Override
public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
+ return mGradientState.mOpaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
}
@Override
@@ -735,6 +742,9 @@ public class GradientDrawable extends Drawable {
mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
colors, st.mPositions, Shader.TileMode.CLAMP));
+ if (!mGradientState.mHasSolidColor) {
+ mFillPaint.setColor(0xff000000);
+ }
} else if (st.mGradient == RADIAL_GRADIENT) {
x0 = r.left + (r.right - r.left) * st.mCenterX;
y0 = r.top + (r.bottom - r.top) * st.mCenterY;
@@ -744,6 +754,9 @@ public class GradientDrawable extends Drawable {
mFillPaint.setShader(new RadialGradient(x0, y0,
level * st.mGradientRadius, colors, null,
Shader.TileMode.CLAMP));
+ if (!mGradientState.mHasSolidColor) {
+ mFillPaint.setColor(0xff000000);
+ }
} else if (st.mGradient == SWEEP_GRADIENT) {
x0 = r.left + (r.right - r.left) * st.mCenterX;
y0 = r.top + (r.bottom - r.top) * st.mCenterY;
@@ -774,6 +787,9 @@ public class GradientDrawable extends Drawable {
}
mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
+ if (!mGradientState.mHasSolidColor) {
+ mFillPaint.setColor(0xff000000);
+ }
}
}
}
@@ -1011,7 +1027,10 @@ public class GradientDrawable extends Drawable {
} else {
Log.w("drawable", "Bad element under <shape>: " + name);
}
+
}
+
+ mGradientState.computeOpacity();
}
private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
@@ -1079,10 +1098,11 @@ public class GradientDrawable extends Drawable {
private float mGradientRadius = 0.5f;
private boolean mUseLevel;
private boolean mUseLevelForShape;
+ private boolean mOpaque;
GradientState(Orientation orientation, int[] colors) {
mOrientation = orientation;
- mColors = colors;
+ setColors(colors);
}
public GradientState(GradientState state) {
@@ -1120,6 +1140,7 @@ public class GradientDrawable extends Drawable {
mGradientRadius = state.mGradientRadius;
mUseLevel = state.mUseLevel;
mUseLevelForShape = state.mUseLevelForShape;
+ mOpaque = state.mOpaque;
}
@Override
@@ -1139,6 +1160,7 @@ public class GradientDrawable extends Drawable {
public void setShape(int shape) {
mShape = shape;
+ computeOpacity();
}
public void setGradientType(int gradient) {
@@ -1153,24 +1175,65 @@ public class GradientDrawable extends Drawable {
public void setColors(int[] colors) {
mHasSolidColor = false;
mColors = colors;
+ computeOpacity();
}
public void setSolidColor(int argb) {
mHasSolidColor = true;
mSolidColor = argb;
mColors = null;
+ computeOpacity();
+ }
+
+ private void computeOpacity() {
+ if (mShape != RECTANGLE) {
+ mOpaque = false;
+ return;
+ }
+
+ if (mRadius > 0 || mRadiusArray != null) {
+ mOpaque = false;
+ return;
+ }
+
+ if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
+ mOpaque = false;
+ return;
+ }
+
+ if (mHasSolidColor) {
+ mOpaque = isOpaque(mSolidColor);
+ return;
+ }
+
+ if (mColors != null) {
+ for (int i = 0; i < mColors.length; i++) {
+ if (!isOpaque(mColors[i])) {
+ mOpaque = false;
+ return;
+ }
+ }
+ }
+
+ mOpaque = true;
+ }
+
+ private static boolean isOpaque(int color) {
+ return ((color >> 24) & 0xff) == 0xff;
}
public void setStroke(int width, int color) {
mStrokeWidth = width;
mStrokeColor = color;
+ computeOpacity();
}
-
+
public void setStroke(int width, int color, float dashWidth, float dashGap) {
mStrokeWidth = width;
mStrokeColor = color;
mStrokeDashWidth = dashWidth;
mStrokeDashGap = dashGap;
+ computeOpacity();
}
public void setCornerRadius(float radius) {
@@ -1180,14 +1243,14 @@ public class GradientDrawable extends Drawable {
mRadius = radius;
mRadiusArray = null;
}
-
+
public void setCornerRadii(float[] radii) {
mRadiusArray = radii;
if (radii == null) {
mRadius = 0;
}
}
-
+
public void setSize(int width, int height) {
mWidth = width;
mHeight = height;
@@ -1202,11 +1265,17 @@ public class GradientDrawable extends Drawable {
mGradientState = state;
initializeWithState(state);
mRectIsDirty = true;
+ mMutated = false;
}
private void initializeWithState(GradientState state) {
if (state.mHasSolidColor) {
mFillPaint.setColor(state.mSolidColor);
+ } else if (state.mColors == null) {
+ // If we don't have a solid color and we don't have a gradient,
+ // the app is stroking the shape, set the color to the default
+ // value of state.mSolidColor
+ mFillPaint.setColor(0);
}
mPadding = state.mPadding;
if (state.mStrokeWidth >= 0) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 383fe71..0351b71 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -590,6 +590,19 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
return this;
}
+ /** @hide */
+ @Override
+ public void setLayoutDirection(int layoutDirection) {
+ if (getLayoutDirection() != layoutDirection) {
+ final ChildDrawable[] array = mLayerState.mChildren;
+ final int N = mLayerState.mNum;
+ for (int i = 0; i < N; i++) {
+ array[i].mDrawable.setLayoutDirection(layoutDirection);
+ }
+ }
+ super.setLayoutDirection(layoutDirection);
+ }
+
static class ChildDrawable {
public Drawable mDrawable;
public int mInsetL, mInsetT, mInsetR, mInsetB;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index b68b267..2ee6233 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -181,7 +181,7 @@ public class NinePatchDrawable extends Drawable {
}
}
- private Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
+ private static Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
int left = Bitmap.scaleFromDensity(insets.left, sdensity, tdensity);
int top = Bitmap.scaleFromDensity(insets.top, sdensity, tdensity);
int right = Bitmap.scaleFromDensity(insets.right, sdensity, tdensity);
@@ -296,7 +296,7 @@ public class NinePatchDrawable extends Drawable {
if (dither) {
options.inDither = false;
}
- options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+ options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
final Rect padding = new Rect();
final Rect layoutInsets = new Rect();
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index ccad250..bd2b2f0 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -221,7 +221,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
}
- final int layoutDirection = getResolvedLayoutDirectionSelf();
+ final int layoutDirection = getLayoutDirection();
Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index a3622a2..2ec1293 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -373,8 +373,16 @@ public class ShapeDrawable extends Drawable {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- mShapeState.mPaint = new Paint(mShapeState.mPaint);
- mShapeState.mPadding = new Rect(mShapeState.mPadding);
+ if (mShapeState.mPaint != null) {
+ mShapeState.mPaint = new Paint(mShapeState.mPaint);
+ } else {
+ mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ }
+ if (mShapeState.mPadding != null) {
+ mShapeState.mPadding = new Rect(mShapeState.mPadding);
+ } else {
+ mShapeState.mPadding = new Rect();
+ }
try {
mShapeState.mShape = mShapeState.mShape.clone();
} catch (CloneNotSupportedException e) {
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 384ca81..f8f3ac9 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -261,6 +261,16 @@ public class StateListDrawable extends DrawableContainer {
return this;
}
+ /** @hide */
+ @Override
+ public void setLayoutDirection(int layoutDirection) {
+ final int numStates = getStateCount();
+ for (int i = 0; i < numStates; i++) {
+ getStateDrawable(i).setLayoutDirection(layoutDirection);
+ }
+ super.setLayoutDirection(layoutDirection);
+ }
+
static final class StateListState extends DrawableContainerState {
int[][] mStateSets;
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
index acc5bd8..39abd4f 100644
--- a/graphics/java/android/renderscript/Matrix2f.java
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 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.
@@ -59,23 +59,23 @@ public class Matrix2f {
/**
* Returns the value for a given row and column
*
- * @param i row of the value to return
- * @param j column of the value to return
+ * @param x column of the value to return
+ * @param y row of the value to return
*
- * @return value in the ith row and jth column
+ * @return value in the yth row and xth column
*/
- public float get(int i, int j) {
- return mMat[i*2 + j];
+ public float get(int x, int y) {
+ return mMat[x*2 + y];
}
/**
* Sets the value for a given row and column
*
- * @param i row of the value to set
- * @param j column of the value to set
+ * @param x column of the value to set
+ * @param y row of the value to set
*/
- public void set(int i, int j, float v) {
- mMat[i*2 + j] = v;
+ public void set(int x, int y, float v) {
+ mMat[x*2 + y] = v;
}
/**
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 253506d..66f2c81 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 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.
@@ -59,23 +59,23 @@ public class Matrix3f {
/**
* Returns the value for a given row and column
*
- * @param i row of the value to return
- * @param j column of the value to return
+ * @param x column of the value to return
+ * @param y row of the value to return
*
- * @return value in the ith row and jth column
+ * @return value in the yth row and xth column
*/
- public float get(int i, int j) {
- return mMat[i*3 + j];
+ public float get(int x, int y) {
+ return mMat[x*3 + y];
}
/**
* Sets the value for a given row and column
*
- * @param i row of the value to set
- * @param j column of the value to set
+ * @param x column of the value to set
+ * @param y row of the value to set
*/
- public void set(int i, int j, float v) {
- mMat[i*3 + j] = v;
+ public void set(int x, int y, float v) {
+ mMat[x*3 + y] = v;
}
/**
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/graphics/java/android/renderscript/Matrix4f.java
index adc1806..4600424 100644
--- a/graphics/java/android/renderscript/Matrix4f.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 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.
@@ -59,23 +59,23 @@ public class Matrix4f {
/**
* Returns the value for a given row and column
*
- * @param i row of the value to return
- * @param j column of the value to return
+ * @param x column of the value to return
+ * @param y row of the value to return
*
- * @return value in the ith row and jth column
+ * @return value in the yth row and xth column
*/
- public float get(int i, int j) {
- return mMat[i*4 + j];
+ public float get(int x, int y) {
+ return mMat[x*4 + y];
}
/**
* Sets the value for a given row and column
*
- * @param i row of the value to set
- * @param j column of the value to set
+ * @param x column of the value to set
+ * @param y row of the value to set
*/
- public void set(int i, int j, float v) {
- mMat[i*4 + j] = v;
+ public void set(int x, int y, float v) {
+ mMat[x*4 + y] = v;
}
/**
@@ -113,6 +113,34 @@ public class Matrix4f {
}
/**
+ * Sets the values of the matrix to those of the parameter
+ *
+ * @param src matrix to load the values from
+ * @hide
+ */
+ public void load(Matrix3f src) {
+ mMat[0] = src.mMat[0];
+ mMat[1] = src.mMat[1];
+ mMat[2] = src.mMat[2];
+ mMat[3] = 0;
+
+ mMat[4] = src.mMat[3];
+ mMat[5] = src.mMat[4];
+ mMat[6] = src.mMat[5];
+ mMat[7] = 0;
+
+ mMat[8] = src.mMat[6];
+ mMat[9] = src.mMat[7];
+ mMat[10] = src.mMat[8];
+ mMat[11] = 0;
+
+ mMat[12] = 0;
+ mMat[13] = 0;
+ mMat[14] = 0;
+ mMat[15] = 1;
+ }
+
+ /**
* Sets current values to be a rotation matrix of certain angle
* about a given axis
*
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2032f67..76edb0a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -561,6 +561,48 @@ public class RenderScript {
return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
}
+ native int rsnScriptIntrinsicCreate(int con, int id, int eid);
+ synchronized int nScriptIntrinsicCreate(int id, int eid) {
+ validate();
+ return rsnScriptIntrinsicCreate(mContext, id, eid);
+ }
+
+ native int rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
+ synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
+ validate();
+ return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
+ }
+
+ native int rsnScriptFieldIDCreate(int con, int sid, int slot);
+ synchronized int nScriptFieldIDCreate(int sid, int slot) {
+ validate();
+ return rsnScriptFieldIDCreate(mContext, sid, slot);
+ }
+
+ native int rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
+ synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
+ validate();
+ return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
+ }
+
+ native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
+ synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
+ validate();
+ rsnScriptGroupSetInput(mContext, group, kernel, alloc);
+ }
+
+ native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
+ synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
+ validate();
+ rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
+ }
+
+ native void rsnScriptGroupExecute(int con, int group);
+ synchronized void nScriptGroupExecute(int group) {
+ validate();
+ rsnScriptGroupExecute(mContext, group);
+ }
+
native int rsnSamplerCreate(int con, int magFilter, int minFilter,
int wrapS, int wrapT, int wrapR, float aniso);
synchronized int nSamplerCreate(int magFilter, int minFilter,
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index bbf5e7e..3fe3261 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -16,10 +16,105 @@
package android.renderscript;
+import android.util.SparseArray;
+
/**
*
**/
public class Script extends BaseObj {
+
+ /**
+ * KernelID is an identifier for a Script + root function pair. It is used
+ * as an identifier for ScriptGroup creation.
+ *
+ * This class should not be directly created. Instead use the method in the
+ * reflected or intrinsic code "getKernelID_funcname()".
+ *
+ */
+ public static final class KernelID extends BaseObj {
+ Script mScript;
+ int mSlot;
+ int mSig;
+ KernelID(int id, RenderScript rs, Script s, int slot, int sig) {
+ super(id, rs);
+ mScript = s;
+ mSlot = slot;
+ mSig = sig;
+ }
+ }
+
+ private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
+ /**
+ * Only to be used by generated reflected classes.
+ *
+ *
+ * @param slot
+ * @param sig
+ * @param ein
+ * @param eout
+ *
+ * @return KernelID
+ */
+ protected KernelID createKernelID(int slot, int sig, Element ein, Element eout) {
+ KernelID k = mKIDs.get(slot);
+ if (k != null) {
+ return k;
+ }
+
+ int id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
+ if (id == 0) {
+ throw new RSDriverException("Failed to create KernelID");
+ }
+
+ k = new KernelID(id, mRS, this, slot, sig);
+ mKIDs.put(slot, k);
+ return k;
+ }
+
+ /**
+ * FieldID is an identifier for a Script + exported field pair. It is used
+ * as an identifier for ScriptGroup creation.
+ *
+ * This class should not be directly created. Instead use the method in the
+ * reflected or intrinsic code "getFieldID_funcname()".
+ *
+ */
+ public static final class FieldID extends BaseObj {
+ Script mScript;
+ int mSlot;
+ FieldID(int id, RenderScript rs, Script s, int slot) {
+ super(id, rs);
+ mScript = s;
+ mSlot = slot;
+ }
+ }
+
+ private final SparseArray<FieldID> mFIDs = new SparseArray();
+ /**
+ * Only to be used by generated reflected classes.
+ *
+ * @param slot
+ * @param e
+ *
+ * @return FieldID
+ */
+ protected FieldID createFieldID(int slot, Element e) {
+ FieldID f = mFIDs.get(slot);
+ if (f != null) {
+ return f;
+ }
+
+ int id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
+ if (id == 0) {
+ throw new RSDriverException("Failed to create FieldID");
+ }
+
+ f = new FieldID(id, mRS, this, slot);
+ mFIDs.put(slot, f);
+ return f;
+ }
+
+
/**
* Only intended for use by generated reflected code.
*
diff --git a/graphics/java/android/renderscript/ScriptGroup.java b/graphics/java/android/renderscript/ScriptGroup.java
new file mode 100644
index 0000000..7afdb39
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptGroup.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * ScriptGroup creates a groups of scripts which are executed
+ * together based upon upon one execution call as if they were
+ * all part of a single script. The scripts may be connected
+ * internally or to an external allocation. For the internal
+ * connections the intermediate results are not observable after
+ * the execution of the script.
+ * <p>
+ * The external connections are grouped into inputs and outputs.
+ * All outputs are produced by a script kernel and placed into a
+ * user supplied allocation. Inputs are similar but supply the
+ * input of a kernal. Inputs bounds to a script are set directly
+ * upon the script.
+ * <p>
+ * A ScriptGroup must contain at least one kernel. A ScriptGroup
+ * must contain only a single directed acyclic graph (DAG) of
+ * script kernels and connections. Attempting to create a
+ * ScriptGroup with multiple DAGs or attempting to create
+ * a cycle within a ScriptGroup will throw an exception.
+ *
+ **/
+public final class ScriptGroup extends BaseObj {
+ IO mOutputs[];
+ IO mInputs[];
+
+ static class IO {
+ Script.KernelID mKID;
+ Allocation mAllocation;
+
+ IO(Script.KernelID s) {
+ mKID = s;
+ }
+ }
+
+ static class ConnectLine {
+ ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
+ mFrom = from;
+ mToK = to;
+ mAllocationType = t;
+ }
+
+ ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
+ mFrom = from;
+ mToF = to;
+ mAllocationType = t;
+ }
+
+ Script.FieldID mToF;
+ Script.KernelID mToK;
+ Script.KernelID mFrom;
+ Type mAllocationType;
+ }
+
+ static class Node {
+ Script mScript;
+ ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
+ ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
+ ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
+ int dagNumber;
+
+ Node mNext;
+
+ Node(Script s) {
+ mScript = s;
+ }
+ }
+
+
+ ScriptGroup(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Sets an input of the ScriptGroup. This specifies an
+ * Allocation to be used for the kernels which require a kernel
+ * input and that input is provided external to the group.
+ *
+ * @param s The ID of the kernel where the allocation should be
+ * connected.
+ * @param a The allocation to connect.
+ */
+ public void setInput(Script.KernelID s, Allocation a) {
+ for (int ct=0; ct < mInputs.length; ct++) {
+ if (mInputs[ct].mKID == s) {
+ mInputs[ct].mAllocation = a;
+ mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
+ return;
+ }
+ }
+ throw new RSIllegalArgumentException("Script not found");
+ }
+
+ /**
+ * Sets an output of the ScriptGroup. This specifies an
+ * Allocation to be used for the kernels which require a kernel
+ * output and that output is provided external to the group.
+ *
+ * @param s The ID of the kernel where the allocation should be
+ * connected.
+ * @param a The allocation to connect.
+ */
+ public void setOutput(Script.KernelID s, Allocation a) {
+ for (int ct=0; ct < mOutputs.length; ct++) {
+ if (mOutputs[ct].mKID == s) {
+ mOutputs[ct].mAllocation = a;
+ mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
+ return;
+ }
+ }
+ throw new RSIllegalArgumentException("Script not found");
+ }
+
+ /**
+ * Execute the ScriptGroup. This will run all the kernels in
+ * the script. The state of the connecting lines will not be
+ * observable after this operation.
+ */
+ public void execute() {
+ mRS.nScriptGroupExecute(getID(mRS));
+ }
+
+
+ /**
+ * Create a ScriptGroup. There are two steps to creating a
+ * ScriptGoup.
+ * <p>
+ * First all the Kernels to be used by the group should be
+ * added. Once this is done the kernels should be connected.
+ * Kernels cannot be added once a connection has been made.
+ * <p>
+ * Second, add connections. There are two forms of connections.
+ * Kernel to Kernel and Kernel to Field. Kernel to Kernel is
+ * higher performance and should be used where possible. The
+ * line of connections cannot form a loop. If a loop is detected
+ * an exception is thrown.
+ * <p>
+ * Once all the connections are made a call to create will
+ * return the ScriptGroup object.
+ *
+ */
+ public static final class Builder {
+ private RenderScript mRS;
+ private ArrayList<Node> mNodes = new ArrayList<Node>();
+ private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
+ private int mKernelCount;
+
+ /**
+ * Create a builder for generating a ScriptGroup.
+ *
+ *
+ * @param rs The Renderscript context.
+ */
+ public Builder(RenderScript rs) {
+ mRS = rs;
+ }
+
+ // do a DFS from original node, looking for original node
+ // any cycle that could be created must contain original node
+ private void validateCycle(Node target, Node original) {
+ for (int ct = 0; ct < target.mOutputs.size(); ct++) {
+ final ConnectLine cl = target.mOutputs.get(ct);
+ if (cl.mToK != null) {
+ Node tn = findNode(cl.mToK.mScript);
+ if (tn.equals(original)) {
+ throw new RSInvalidStateException("Loops in group not allowed.");
+ }
+ validateCycle(tn, original);
+ }
+ if (cl.mToF != null) {
+ Node tn = findNode(cl.mToF.mScript);
+ if (tn.equals(original)) {
+ throw new RSInvalidStateException("Loops in group not allowed.");
+ }
+ validateCycle(tn, original);
+ }
+ }
+ }
+
+ private void mergeDAGs(int valueUsed, int valueKilled) {
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ if (mNodes.get(ct).dagNumber == valueKilled)
+ mNodes.get(ct).dagNumber = valueUsed;
+ }
+ }
+
+ private void validateDAGRecurse(Node n, int dagNumber) {
+ // combine DAGs if this node has been seen already
+ if (n.dagNumber != 0 && n.dagNumber != dagNumber) {
+ mergeDAGs(n.dagNumber, dagNumber);
+ return;
+ }
+
+ n.dagNumber = dagNumber;
+ for (int ct=0; ct < n.mOutputs.size(); ct++) {
+ final ConnectLine cl = n.mOutputs.get(ct);
+ if (cl.mToK != null) {
+ Node tn = findNode(cl.mToK.mScript);
+ validateDAGRecurse(tn, dagNumber);
+ }
+ if (cl.mToF != null) {
+ Node tn = findNode(cl.mToF.mScript);
+ validateDAGRecurse(tn, dagNumber);
+ }
+ }
+ }
+
+ private void validateDAG() {
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ Node n = mNodes.get(ct);
+ if (n.mInputs.size() == 0) {
+ if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
+ throw new RSInvalidStateException("Groups cannot contain unconnected scripts");
+ }
+ validateDAGRecurse(n, ct+1);
+ }
+ }
+ int dagNumber = mNodes.get(0).dagNumber;
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ if (mNodes.get(ct).dagNumber != dagNumber) {
+ throw new RSInvalidStateException("Multiple DAGs in group not allowed.");
+ }
+ }
+ }
+
+ private Node findNode(Script s) {
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ if (s == mNodes.get(ct).mScript) {
+ return mNodes.get(ct);
+ }
+ }
+ return null;
+ }
+
+ private Node findNode(Script.KernelID k) {
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ Node n = mNodes.get(ct);
+ for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+ if (k == n.mKernels.get(ct2)) {
+ return n;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a Kernel to the group.
+ *
+ *
+ * @param k The kernel to add.
+ *
+ * @return Builder Returns this.
+ */
+ public Builder addKernel(Script.KernelID k) {
+ if (mLines.size() != 0) {
+ throw new RSInvalidStateException(
+ "Kernels may not be added once connections exist.");
+ }
+
+ //android.util.Log.v("RSR", "addKernel 1 k=" + k);
+ if (findNode(k) != null) {
+ return this;
+ }
+ //android.util.Log.v("RSR", "addKernel 2 ");
+ mKernelCount++;
+ Node n = findNode(k.mScript);
+ if (n == null) {
+ //android.util.Log.v("RSR", "addKernel 3 ");
+ n = new Node(k.mScript);
+ mNodes.add(n);
+ }
+ n.mKernels.add(k);
+ return this;
+ }
+
+ /**
+ * Adds a connection to the group.
+ *
+ *
+ * @param t The type of the connection. This is used to
+ * determine the kernel launch sizes on the source side
+ * of this connection.
+ * @param from The source for the connection.
+ * @param to The destination of the connection.
+ *
+ * @return Builder Returns this
+ */
+ public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
+ //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+ Node nf = findNode(from);
+ if (nf == null) {
+ throw new RSInvalidStateException("From script not found.");
+ }
+
+ Node nt = findNode(to.mScript);
+ if (nt == null) {
+ throw new RSInvalidStateException("To script not found.");
+ }
+
+ ConnectLine cl = new ConnectLine(t, from, to);
+ mLines.add(new ConnectLine(t, from, to));
+
+ nf.mOutputs.add(cl);
+ nt.mInputs.add(cl);
+
+ validateCycle(nf, nf);
+ return this;
+ }
+
+ /**
+ * Adds a connection to the group.
+ *
+ *
+ * @param t The type of the connection. This is used to
+ * determine the kernel launch sizes for both sides of
+ * this connection.
+ * @param from The source for the connection.
+ * @param to The destination of the connection.
+ *
+ * @return Builder Returns this
+ */
+ public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
+ //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+ Node nf = findNode(from);
+ if (nf == null) {
+ throw new RSInvalidStateException("From script not found.");
+ }
+
+ Node nt = findNode(to);
+ if (nt == null) {
+ throw new RSInvalidStateException("To script not found.");
+ }
+
+ ConnectLine cl = new ConnectLine(t, from, to);
+ mLines.add(new ConnectLine(t, from, to));
+
+ nf.mOutputs.add(cl);
+ nt.mInputs.add(cl);
+
+ validateCycle(nf, nf);
+ return this;
+ }
+
+
+
+ /**
+ * Creates the Script group.
+ *
+ *
+ * @return ScriptGroup The new ScriptGroup
+ */
+ public ScriptGroup create() {
+
+ if (mNodes.size() == 0) {
+ throw new RSInvalidStateException("Empty script groups are not allowed");
+ }
+
+ // reset DAG numbers in case we're building a second group
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ mNodes.get(ct).dagNumber = 0;
+ }
+ validateDAG();
+
+ ArrayList<IO> inputs = new ArrayList<IO>();
+ ArrayList<IO> outputs = new ArrayList<IO>();
+
+ int[] kernels = new int[mKernelCount];
+ int idx = 0;
+ for (int ct=0; ct < mNodes.size(); ct++) {
+ Node n = mNodes.get(ct);
+ for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+ final Script.KernelID kid = n.mKernels.get(ct2);
+ kernels[idx++] = kid.getID(mRS);
+
+ boolean hasInput = false;
+ boolean hasOutput = false;
+ for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
+ if (n.mInputs.get(ct3).mToK == kid) {
+ hasInput = true;
+ }
+ }
+ for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
+ if (n.mOutputs.get(ct3).mFrom == kid) {
+ hasOutput = true;
+ }
+ }
+ if (!hasInput) {
+ inputs.add(new IO(kid));
+ }
+ if (!hasOutput) {
+ outputs.add(new IO(kid));
+ }
+
+ }
+ }
+ if (idx != mKernelCount) {
+ throw new RSRuntimeException("Count mismatch, should not happen.");
+ }
+
+ int[] src = new int[mLines.size()];
+ int[] dstk = new int[mLines.size()];
+ int[] dstf = new int[mLines.size()];
+ int[] types = new int[mLines.size()];
+
+ for (int ct=0; ct < mLines.size(); ct++) {
+ ConnectLine cl = mLines.get(ct);
+ src[ct] = cl.mFrom.getID(mRS);
+ if (cl.mToK != null) {
+ dstk[ct] = cl.mToK.getID(mRS);
+ }
+ if (cl.mToF != null) {
+ dstf[ct] = cl.mToF.getID(mRS);
+ }
+ types[ct] = cl.mAllocationType.getID(mRS);
+ }
+
+ int id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
+ if (id == 0) {
+ throw new RSRuntimeException("Object creation error, should not happen.");
+ }
+
+ ScriptGroup sg = new ScriptGroup(id, mRS);
+ sg.mOutputs = new IO[outputs.size()];
+ for (int ct=0; ct < outputs.size(); ct++) {
+ sg.mOutputs[ct] = outputs.get(ct);
+ }
+
+ sg.mInputs = new IO[inputs.size()];
+ for (int ct=0; ct < inputs.size(); ct++) {
+ sg.mInputs[ct] = inputs.get(ct);
+ }
+
+ return sg;
+ }
+
+ }
+
+
+}
+
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic.java b/graphics/java/android/renderscript/ScriptIntrinsic.java
new file mode 100644
index 0000000..f54943a
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsic.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+
+/**
+ * Base class for all Intrinsic scripts. An intrinsic a script
+ * which implements a pre-defined function. Intrinsics are
+ * provided to provide effecient implemtations of common
+ * operations.
+ *
+ * Not intended for direct use.
+ **/
+public abstract class ScriptIntrinsic extends Script {
+ ScriptIntrinsic(int id, RenderScript rs) {
+ super(id, rs);
+ }
+}
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlend.java b/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
new file mode 100644
index 0000000..65c69c0
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+
+/**
+ * Intrinsic kernels for blending two buffers. Each blend function is a separate
+ * kernel to make it easy to change between blend modes.
+ **/
+public class ScriptIntrinsicBlend extends ScriptIntrinsic {
+ ScriptIntrinsicBlend(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Supported elements types are uchar4
+ *
+ *
+ * @param rs
+ * @param e
+ *
+ * @return ScriptIntrinsicBlend
+ */
+ public static ScriptIntrinsicBlend create(RenderScript rs, Element e) {
+ // 7 comes from RS_SCRIPT_INTRINSIC_ID_BLEND in rsDefines.h
+ int id = rs.nScriptIntrinsicCreate(7, e.getID(rs));
+ return new ScriptIntrinsicBlend(id, rs);
+
+ }
+
+ private void blend(int id, Allocation ain, Allocation aout) {
+ if (!ain.getElement().isCompatible(Element.U8_4(mRS))) {
+ throw new RSIllegalArgumentException("Input is not of expected format.");
+ }
+ if (!aout.getElement().isCompatible(Element.U8_4(mRS))) {
+ throw new RSIllegalArgumentException("Output is not of expected format.");
+ }
+ forEach(id, ain, aout, null);
+ }
+
+ /**
+ * dst = {0, 0, 0, 0}
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachClear(Allocation ain, Allocation aout) {
+ blend(0, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the Clear kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDClear() {
+ return createKernelID(0, 3, null, null);
+ }
+
+
+ /**
+ * dst = src
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachSrc(Allocation ain, Allocation aout) {
+ blend(1, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the Src kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDSrc() {
+ return createKernelID(1, 3, null, null);
+ }
+
+ /**
+ * dst = dst
+ * This is a NOP
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachDst(Allocation ain, Allocation aout) {
+ // NOP
+ }
+
+ /**
+ * Get a KernelID for the Dst kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDDst() {
+ return createKernelID(2, 3, null, null);
+ }
+
+ /**
+ * dst = src + dst * (1.0 - src.a)
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachSrcOver(Allocation ain, Allocation aout) {
+ blend(3, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the SrcOver kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDSrcOver() {
+ return createKernelID(3, 3, null, null);
+ }
+
+ /**
+ * dst = dst + src * (1.0 - dst.a)
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachDstOver(Allocation ain, Allocation aout) {
+ blend(4, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the DstOver kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDDstOver() {
+ return createKernelID(4, 3, null, null);
+ }
+
+ /**
+ * dst = src * dst.a
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachSrcIn(Allocation ain, Allocation aout) {
+ blend(5, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the SrcIn kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDSrcIn() {
+ return createKernelID(5, 3, null, null);
+ }
+
+ /**
+ * dst = dst * src.a
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachDstIn(Allocation ain, Allocation aout) {
+ blend(6, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the DstIn kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDDstIn() {
+ return createKernelID(6, 3, null, null);
+ }
+
+ /**
+ * dst = src * (1.0 - dst.a)
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachSrcOut(Allocation ain, Allocation aout) {
+ blend(7, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the SrcOut kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDSrcOut() {
+ return createKernelID(7, 3, null, null);
+ }
+
+ /**
+ * dst = dst * (1.0 - src.a)
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachDstOut(Allocation ain, Allocation aout) {
+ blend(8, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the DstOut kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDDstOut() {
+ return createKernelID(8, 3, null, null);
+ }
+
+ /**
+ * dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb
+ * dst.a = dst.a
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachSrcAtop(Allocation ain, Allocation aout) {
+ blend(9, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the SrcAtop kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDSrcAtop() {
+ return createKernelID(9, 3, null, null);
+ }
+
+ /**
+ * dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb
+ * dst.a = src.a
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachDstAtop(Allocation ain, Allocation aout) {
+ blend(10, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the DstAtop kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDDstAtop() {
+ return createKernelID(10, 3, null, null);
+ }
+
+ /**
+ * dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachXor(Allocation ain, Allocation aout) {
+ blend(11, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the Xor kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDXor() {
+ return createKernelID(11, 3, null, null);
+ }
+
+ ////////
+/*
+ public void forEachNormal(Allocation ain, Allocation aout) {
+ blend(12, ain, aout);
+ }
+
+ public void forEachAverage(Allocation ain, Allocation aout) {
+ blend(13, ain, aout);
+ }
+*/
+ /**
+ * dst = src * dst
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachMultiply(Allocation ain, Allocation aout) {
+ blend(14, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the Multiply kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDMultiply() {
+ return createKernelID(14, 3, null, null);
+ }
+
+/*
+ public void forEachScreen(Allocation ain, Allocation aout) {
+ blend(15, ain, aout);
+ }
+
+ public void forEachDarken(Allocation ain, Allocation aout) {
+ blend(16, ain, aout);
+ }
+
+ public void forEachLighten(Allocation ain, Allocation aout) {
+ blend(17, ain, aout);
+ }
+
+ public void forEachOverlay(Allocation ain, Allocation aout) {
+ blend(18, ain, aout);
+ }
+
+ public void forEachHardlight(Allocation ain, Allocation aout) {
+ blend(19, ain, aout);
+ }
+
+ public void forEachSoftlight(Allocation ain, Allocation aout) {
+ blend(20, ain, aout);
+ }
+
+ public void forEachDifference(Allocation ain, Allocation aout) {
+ blend(21, ain, aout);
+ }
+
+ public void forEachNegation(Allocation ain, Allocation aout) {
+ blend(22, ain, aout);
+ }
+
+ public void forEachExclusion(Allocation ain, Allocation aout) {
+ blend(23, ain, aout);
+ }
+
+ public void forEachColorDodge(Allocation ain, Allocation aout) {
+ blend(24, ain, aout);
+ }
+
+ public void forEachInverseColorDodge(Allocation ain, Allocation aout) {
+ blend(25, ain, aout);
+ }
+
+ public void forEachSoftDodge(Allocation ain, Allocation aout) {
+ blend(26, ain, aout);
+ }
+
+ public void forEachColorBurn(Allocation ain, Allocation aout) {
+ blend(27, ain, aout);
+ }
+
+ public void forEachInverseColorBurn(Allocation ain, Allocation aout) {
+ blend(28, ain, aout);
+ }
+
+ public void forEachSoftBurn(Allocation ain, Allocation aout) {
+ blend(29, ain, aout);
+ }
+
+ public void forEachReflect(Allocation ain, Allocation aout) {
+ blend(30, ain, aout);
+ }
+
+ public void forEachGlow(Allocation ain, Allocation aout) {
+ blend(31, ain, aout);
+ }
+
+ public void forEachFreeze(Allocation ain, Allocation aout) {
+ blend(32, ain, aout);
+ }
+
+ public void forEachHeat(Allocation ain, Allocation aout) {
+ blend(33, ain, aout);
+ }
+*/
+ /**
+ * dst = min(src + dst, 1.0)
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachAdd(Allocation ain, Allocation aout) {
+ blend(34, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the Add kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDAdd() {
+ return createKernelID(34, 3, null, null);
+ }
+
+ /**
+ * dst = max(dst - src, 0.0)
+ *
+ * @param ain The source buffer
+ * @param aout The destination buffer
+ */
+ public void forEachSubtract(Allocation ain, Allocation aout) {
+ blend(35, ain, aout);
+ }
+
+ /**
+ * Get a KernelID for the Subtract kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelIDSubtract() {
+ return createKernelID(35, 3, null, null);
+ }
+
+/*
+ public void forEachStamp(Allocation ain, Allocation aout) {
+ blend(36, ain, aout);
+ }
+
+ public void forEachRed(Allocation ain, Allocation aout) {
+ blend(37, ain, aout);
+ }
+
+ public void forEachGreen(Allocation ain, Allocation aout) {
+ blend(38, ain, aout);
+ }
+
+ public void forEachBlue(Allocation ain, Allocation aout) {
+ blend(39, ain, aout);
+ }
+
+ public void forEachHue(Allocation ain, Allocation aout) {
+ blend(40, ain, aout);
+ }
+
+ public void forEachSaturation(Allocation ain, Allocation aout) {
+ blend(41, ain, aout);
+ }
+
+ public void forEachColor(Allocation ain, Allocation aout) {
+ blend(42, ain, aout);
+ }
+
+ public void forEachLuminosity(Allocation ain, Allocation aout) {
+ blend(43, ain, aout);
+ }
+*/
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
new file mode 100644
index 0000000..11164e3
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic Gausian blur filter. Applies a gaussian blur of the
+ * specified radius to all elements of an allocation.
+ *
+ *
+ **/
+public final class ScriptIntrinsicBlur extends ScriptIntrinsic {
+ private final float[] mValues = new float[9];
+ private Allocation mInput;
+
+ private ScriptIntrinsicBlur(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Create an intrinsic for applying a blur to an allocation. The
+ * default radius is 5.0.
+ *
+ * Supported elements types are {@link Element#U8_4}
+ *
+ * @param rs The Renderscript context
+ * @param e Element type for inputs and outputs
+ *
+ * @return ScriptIntrinsicBlur
+ */
+ public static ScriptIntrinsicBlur create(RenderScript rs, Element e) {
+ if (e != Element.U8_4(rs)) {
+ throw new RSIllegalArgumentException("Unsuported element type.");
+ }
+ int id = rs.nScriptIntrinsicCreate(5, e.getID(rs));
+ ScriptIntrinsicBlur sib = new ScriptIntrinsicBlur(id, rs);
+ sib.setRadius(5.f);
+ return sib;
+ }
+
+ /**
+ * Set the input of the blur.
+ * Must match the element type supplied during create.
+ *
+ * @param ain The input allocation
+ */
+ public void setInput(Allocation ain) {
+ mInput = ain;
+ setVar(1, ain);
+ }
+
+ /**
+ * Set the radius of the Blur.
+ *
+ * Supported range 0 < radius <= 25
+ *
+ * @param radius The radius of the blur
+ */
+ public void setRadius(float radius) {
+ if (radius <= 0 || radius > 25) {
+ throw new RSIllegalArgumentException("Radius out of range (0 < r <= 25).");
+ }
+ setVar(0, radius);
+ }
+
+ /**
+ * Apply the filter to the input and save to the specified
+ * allocation.
+ *
+ * @param aout Output allocation. Must match creation element
+ * type.
+ */
+ public void forEach(Allocation aout) {
+ forEach(0, null, aout, null);
+ }
+
+ /**
+ * Get a KernelID for this intrinsic kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelID() {
+ return createKernelID(0, 2, null, null);
+ }
+
+ /**
+ * Get a FieldID for the input field of this intrinsic.
+ *
+ * @return Script.FieldID The FieldID object.
+ */
+ public Script.FieldID getFieldID_Input() {
+ return createFieldID(1, null);
+ }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
new file mode 100644
index 0000000..cb458ba
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a color matrix to allocations.
+ *
+ * This has the same effect as loading each element and
+ * converting it to a {@link Element#F32_4}, multiplying the
+ * result by the 4x4 color matrix as performed by
+ * rsMatrixMultiply() and writing it to the output after
+ * conversion back to {@link Element#U8_4}.
+ **/
+public final class ScriptIntrinsicColorMatrix extends ScriptIntrinsic {
+ private final Matrix4f mMatrix = new Matrix4f();
+ private Allocation mInput;
+
+ private ScriptIntrinsicColorMatrix(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Create an intrinsic for applying a color matrix to an
+ * allocation.
+ *
+ * Supported elements types are {@link Element#U8_4}
+ *
+ * @param rs The Renderscript context
+ * @param e Element type for intputs and outputs
+ *
+ * @return ScriptIntrinsicColorMatrix
+ */
+ public static ScriptIntrinsicColorMatrix create(RenderScript rs, Element e) {
+ if (e != Element.U8_4(rs)) {
+ throw new RSIllegalArgumentException("Unsuported element type.");
+ }
+ int id = rs.nScriptIntrinsicCreate(2, e.getID(rs));
+ return new ScriptIntrinsicColorMatrix(id, rs);
+
+ }
+
+ private void setMatrix() {
+ FieldPacker fp = new FieldPacker(16*4);
+ fp.addMatrix(mMatrix);
+ setVar(0, fp);
+ }
+
+ /**
+ * Set the color matrix which will be applied to each cell of
+ * the image.
+ *
+ * @param m The 4x4 matrix to set.
+ */
+ public void setColorMatrix(Matrix4f m) {
+ mMatrix.load(m);
+ setMatrix();
+ }
+
+ /**
+ * Set the color matrix which will be applied to each cell of the image.
+ * This will set the alpha channel to be a copy.
+ *
+ * @param m The 3x3 matrix to set.
+ */
+ public void setColorMatrix(Matrix3f m) {
+ mMatrix.load(m);
+ setMatrix();
+ }
+
+ /**
+ * Set a color matrix to convert from RGB to luminance. The alpha channel
+ * will be a copy.
+ *
+ */
+ public void setGreyscale() {
+ mMatrix.loadIdentity();
+ mMatrix.set(0, 0, 0.299f);
+ mMatrix.set(1, 0, 0.587f);
+ mMatrix.set(2, 0, 0.114f);
+ mMatrix.set(0, 1, 0.299f);
+ mMatrix.set(1, 1, 0.587f);
+ mMatrix.set(2, 1, 0.114f);
+ mMatrix.set(0, 2, 0.299f);
+ mMatrix.set(1, 2, 0.587f);
+ mMatrix.set(2, 2, 0.114f);
+ setMatrix();
+ }
+
+ /**
+ * Set the matrix to convert from YUV to RGB with a direct copy of the 4th
+ * channel.
+ *
+ */
+ public void setYUVtoRGB() {
+ mMatrix.loadIdentity();
+ mMatrix.set(0, 0, 1.f);
+ mMatrix.set(1, 0, 0.f);
+ mMatrix.set(2, 0, 1.13983f);
+ mMatrix.set(0, 1, 1.f);
+ mMatrix.set(1, 1, -0.39465f);
+ mMatrix.set(2, 1, -0.5806f);
+ mMatrix.set(0, 2, 1.f);
+ mMatrix.set(1, 2, 2.03211f);
+ mMatrix.set(2, 2, 0.f);
+ setMatrix();
+ }
+
+ /**
+ * Set the matrix to convert from RGB to YUV with a direct copy of the 4th
+ * channel.
+ *
+ */
+ public void setRGBtoYUV() {
+ mMatrix.loadIdentity();
+ mMatrix.set(0, 0, 0.299f);
+ mMatrix.set(1, 0, 0.587f);
+ mMatrix.set(2, 0, 0.114f);
+ mMatrix.set(0, 1, -0.14713f);
+ mMatrix.set(1, 1, -0.28886f);
+ mMatrix.set(2, 1, 0.436f);
+ mMatrix.set(0, 2, 0.615f);
+ mMatrix.set(1, 2, -0.51499f);
+ mMatrix.set(2, 2, -0.10001f);
+ setMatrix();
+ }
+
+
+ /**
+ * Invoke the kernel and apply the matrix to each cell of ain and copy to
+ * aout.
+ *
+ * @param ain Input allocation
+ * @param aout Output allocation
+ */
+ public void forEach(Allocation ain, Allocation aout) {
+ forEach(0, ain, aout, null);
+ }
+
+ /**
+ * Get a KernelID for this intrinsic kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelID() {
+ return createKernelID(0, 3, null, null);
+ }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
new file mode 100644
index 0000000..91efa02
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a 3x3 convolve to an allocation.
+ *
+ **/
+public final class ScriptIntrinsicConvolve3x3 extends ScriptIntrinsic {
+ private final float[] mValues = new float[9];
+ private Allocation mInput;
+
+ private ScriptIntrinsicConvolve3x3(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Supported elements types are {@link Element#U8_4}
+ *
+ * The default coefficients are.
+ *
+ * <code>
+ * <p> [ 0, 0, 0 ]
+ * <p> [ 0, 1, 0 ]
+ * <p> [ 0, 0, 0 ]
+ * </code>
+ *
+ * @param rs The Renderscript context
+ * @param e Element type for intputs and outputs
+ *
+ * @return ScriptIntrinsicConvolve3x3
+ */
+ public static ScriptIntrinsicConvolve3x3 create(RenderScript rs, Element e) {
+ float f[] = { 0, 0, 0, 0, 1, 0, 0, 0, 0};
+ if (e != Element.U8_4(rs)) {
+ throw new RSIllegalArgumentException("Unsuported element type.");
+ }
+ int id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
+ ScriptIntrinsicConvolve3x3 si = new ScriptIntrinsicConvolve3x3(id, rs);
+ si.setCoefficients(f);
+ return si;
+
+ }
+
+ /**
+ * Set the input of the blur.
+ * Must match the element type supplied during create.
+ *
+ * @param ain The input allocation.
+ */
+ public void setInput(Allocation ain) {
+ mInput = ain;
+ setVar(1, ain);
+ }
+
+ /**
+ * Set the coefficients for the convolve.
+ *
+ * The convolve layout is
+ * <code>
+ * <p> [ 0, 1, 2 ]
+ * <p> [ 3, 4, 5 ]
+ * <p> [ 6, 7, 8 ]
+ * </code>
+ *
+ * @param v The array of coefficients to set
+ */
+ public void setCoefficients(float v[]) {
+ FieldPacker fp = new FieldPacker(9*4);
+ for (int ct=0; ct < mValues.length; ct++) {
+ mValues[ct] = v[ct];
+ fp.addF32(mValues[ct]);
+ }
+ setVar(0, fp);
+ }
+
+ /**
+ * Apply the filter to the input and save to the specified
+ * allocation.
+ *
+ * @param aout Output allocation. Must match creation element
+ * type.
+ */
+ public void forEach(Allocation aout) {
+ forEach(0, null, aout, null);
+ }
+
+ /**
+ * Get a KernelID for this intrinsic kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelID() {
+ return createKernelID(0, 2, null, null);
+ }
+
+ /**
+ * Get a FieldID for the input field of this intrinsic.
+ *
+ * @return Script.FieldID The FieldID object.
+ */
+ public Script.FieldID getFieldID_Input() {
+ return createFieldID(1, null);
+ }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
new file mode 100644
index 0000000..1f52e3f
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a 5x5 convolve to an allocation.
+ *
+ **/
+public final class ScriptIntrinsicConvolve5x5 extends ScriptIntrinsic {
+ private final float[] mValues = new float[25];
+ private Allocation mInput;
+
+ private ScriptIntrinsicConvolve5x5(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Supported elements types are {@link Element#U8_4}
+ *
+ * The default coefficients are.
+ * <code>
+ * <p> [ 0, 0, 0, 0, 0 ]
+ * <p> [ 0, 0, 0, 0, 0 ]
+ * <p> [ 0, 0, 1, 0, 0 ]
+ * <p> [ 0, 0, 0, 0, 0 ]
+ * <p> [ 0, 0, 0, 0, 0 ]
+ * </code>
+ *
+ * @param rs The Renderscript context
+ * @param e Element type for intputs and outputs
+ *
+ * @return ScriptIntrinsicConvolve5x5
+ */
+ public static ScriptIntrinsicConvolve5x5 create(RenderScript rs, Element e) {
+ int id = rs.nScriptIntrinsicCreate(4, e.getID(rs));
+ return new ScriptIntrinsicConvolve5x5(id, rs);
+
+ }
+
+ /**
+ * Set the input of the blur.
+ * Must match the element type supplied during create.
+ *
+ * @param ain The input allocation.
+ */
+ public void setInput(Allocation ain) {
+ mInput = ain;
+ setVar(1, ain);
+ }
+
+ /**
+ * Set the coefficients for the convolve.
+ *
+ * The convolve layout is
+ * <code>
+ * <p> [ 0, 1, 2, 3, 4 ]
+ * <p> [ 5, 6, 7, 8, 9 ]
+ * <p> [ 10, 11, 12, 13, 14 ]
+ * <p> [ 15, 16, 17, 18, 19 ]
+ * <p> [ 20, 21, 22, 23, 24 ]
+ * </code>
+ *
+ * @param v The array of coefficients to set
+ */
+ public void setCoefficients(float v[]) {
+ FieldPacker fp = new FieldPacker(25*4);
+ for (int ct=0; ct < mValues.length; ct++) {
+ mValues[ct] = v[ct];
+ fp.addF32(mValues[ct]);
+ }
+ setVar(0, fp);
+ }
+
+ /**
+ * Apply the filter to the input and save to the specified
+ * allocation.
+ *
+ * @param aout Output allocation. Must match creation element
+ * type.
+ */
+ public void forEach(Allocation aout) {
+ forEach(0, null, aout, null);
+ }
+
+ /**
+ * Get a KernelID for this intrinsic kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelID() {
+ return createKernelID(0, 2, null, null);
+ }
+
+ /**
+ * Get a FieldID for the input field of this intrinsic.
+ *
+ * @return Script.FieldID The FieldID object.
+ */
+ public Script.FieldID getFieldID_Input() {
+ return createFieldID(1, null);
+ }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
new file mode 100644
index 0000000..41bdd25
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a per-channel lookup table. Each
+ * channel of the input has an independant lookup table. The
+ * tables are 256 entries in size and can cover the full value
+ * range of {@link Element#U8_4}.
+ **/
+public final class ScriptIntrinsicLUT extends ScriptIntrinsic {
+ private final Matrix4f mMatrix = new Matrix4f();
+ private Allocation mTables;
+ private final byte mCache[] = new byte[1024];
+ private boolean mDirty = true;
+
+ private ScriptIntrinsicLUT(int id, RenderScript rs) {
+ super(id, rs);
+ mTables = Allocation.createSized(rs, Element.U8(rs), 1024);
+ for (int ct=0; ct < 256; ct++) {
+ mCache[ct] = (byte)ct;
+ mCache[ct + 256] = (byte)ct;
+ mCache[ct + 512] = (byte)ct;
+ mCache[ct + 768] = (byte)ct;
+ }
+ setVar(0, mTables);
+ }
+
+ /**
+ * Supported elements types are {@link Element#U8_4}
+ *
+ * The defaults tables are identity.
+ *
+ * @param rs The Renderscript context
+ * @param e Element type for intputs and outputs
+ *
+ * @return ScriptIntrinsicLUT
+ */
+ public static ScriptIntrinsicLUT create(RenderScript rs, Element e) {
+ int id = rs.nScriptIntrinsicCreate(3, e.getID(rs));
+ return new ScriptIntrinsicLUT(id, rs);
+
+ }
+
+
+ private void validate(int index, int value) {
+ if (index < 0 || index > 255) {
+ throw new RSIllegalArgumentException("Index out of range (0-255).");
+ }
+ if (value < 0 || value > 255) {
+ throw new RSIllegalArgumentException("Value out of range (0-255).");
+ }
+ }
+
+ /**
+ * Set an entry in the red channel lookup table
+ *
+ * @param index Must be 0-255
+ * @param value Must be 0-255
+ */
+ public void setRed(int index, int value) {
+ validate(index, value);
+ mCache[index] = (byte)value;
+ mDirty = true;
+ }
+
+ /**
+ * Set an entry in the green channel lookup table
+ *
+ * @param index Must be 0-255
+ * @param value Must be 0-255
+ */
+ public void setGreen(int index, int value) {
+ validate(index, value);
+ mCache[index+256] = (byte)value;
+ mDirty = true;
+ }
+
+ /**
+ * Set an entry in the blue channel lookup table
+ *
+ * @param index Must be 0-255
+ * @param value Must be 0-255
+ */
+ public void setBlue(int index, int value) {
+ validate(index, value);
+ mCache[index+512] = (byte)value;
+ mDirty = true;
+ }
+
+ /**
+ * Set an entry in the alpha channel lookup table
+ *
+ * @param index Must be 0-255
+ * @param value Must be 0-255
+ */
+ public void setAlpha(int index, int value) {
+ validate(index, value);
+ mCache[index+768] = (byte)value;
+ mDirty = true;
+ }
+
+
+ /**
+ * Invoke the kernel and apply the lookup to each cell of ain
+ * and copy to aout.
+ *
+ * @param ain Input allocation
+ * @param aout Output allocation
+ */
+ public void forEach(Allocation ain, Allocation aout) {
+ if (mDirty) {
+ mDirty = false;
+ mTables.copyFromUnchecked(mCache);
+ }
+ forEach(0, ain, aout, null);
+ }
+
+ /**
+ * Get a KernelID for this intrinsic kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelID() {
+ return createKernelID(0, 3, null, null);
+ }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
new file mode 100644
index 0000000..dc8a5aa
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 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.renderscript;
+
+
+/**
+ * Intrinsic for converting an Android YUV buffer to RGB.
+ *
+ * The input allocation is supplied in NV21 format as a U8
+ * element type. The output is RGBA, the alpha channel will be
+ * set to 255.
+ */
+public final class ScriptIntrinsicYuvToRGB extends ScriptIntrinsic {
+ private Allocation mInput;
+
+ ScriptIntrinsicYuvToRGB(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Create an intrinsic for converting YUV to RGB.
+ *
+ * Supported elements types are {@link Element#U8_4}
+ *
+ * @param rs The Renderscript context
+ * @param e Element type for output
+ *
+ * @return ScriptIntrinsicYuvToRGB
+ */
+ public static ScriptIntrinsicYuvToRGB create(RenderScript rs, Element e) {
+ // 6 comes from RS_SCRIPT_INTRINSIC_YUV_TO_RGB in rsDefines.h
+ int id = rs.nScriptIntrinsicCreate(6, e.getID(rs));
+ ScriptIntrinsicYuvToRGB si = new ScriptIntrinsicYuvToRGB(id, rs);
+ return si;
+ }
+
+
+ /**
+ * Set the input yuv allocation, must be {@link Element#U8}.
+ *
+ * @param ain The input allocation.
+ */
+ public void setInput(Allocation ain) {
+ mInput = ain;
+ setVar(0, ain);
+ }
+
+ /**
+ * Convert the image to RGB.
+ *
+ * @param aout Output allocation. Must match creation element
+ * type.
+ */
+ public void forEach(Allocation aout) {
+ forEach(0, null, aout, null);
+ }
+
+ /**
+ * Get a KernelID for this intrinsic kernel.
+ *
+ * @return Script.KernelID The KernelID object.
+ */
+ public Script.KernelID getKernelID() {
+ return createKernelID(0, 2, null, null);
+ }
+
+ /**
+ * Get a FieldID for the input field of this intrinsic.
+ *
+ * @return Script.FieldID The FieldID object.
+ */
+ public Script.FieldID getFieldID_Input() {
+ return createFieldID(0, null);
+ }
+}