summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/GLES20Canvas.java11
-rw-r--r--core/jni/android/graphics/Shader.cpp75
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp9
-rw-r--r--graphics/java/android/graphics/LinearGradient.java41
-rw-r--r--libs/hwui/OpenGLRenderer.cpp19
-rw-r--r--libs/hwui/OpenGLRenderer.h11
-rw-r--r--libs/hwui/Snapshot.h32
7 files changed, 161 insertions, 37 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 676aae3..ef9709e 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -631,7 +631,10 @@ class GLES20Canvas extends Canvas {
bs.mTileX, bs.mTileY, bs.mLocalMatrix);
return true;
} else if (shader instanceof LinearGradient) {
- // TODO: Implement
+ final LinearGradient ls = (LinearGradient) shader;
+ nSetupLinearShader(mRenderer, ls.native_instance, ls.bounds, ls.colors,
+ ls.positions, ls.tileMode, ls.mLocalMatrix);
+ return true;
} else if (shader instanceof RadialGradient) {
// TODO: Implement
} else if (shader instanceof SweepGradient) {
@@ -640,8 +643,10 @@ class GLES20Canvas extends Canvas {
}
return false;
}
-
+
+ private native void nSetupLinearShader(int renderer, int shader, int bounds,
+ int colors, int positions, int tileMode, int localMatrix);
private native void nSetupBitmapShader(int renderer, int shader, int bitmap,
int tileX, int tileY, int matrix);
- private native void nResetShader(int renderer);
+ private native void nResetShader(int renderer);
}
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b09c62b..eb600c4 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -8,6 +8,13 @@
#include "SkTemplates.h"
#include "SkXfermode.h"
+static struct {
+ jclass clazz;
+ jfieldID bounds;
+ jfieldID colors;
+ jfieldID positions;
+} gLinearGradientClassInfo;
+
static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
if (NULL == ptr) {
doThrowIAE(env);
@@ -77,7 +84,14 @@ static SkShader* BitmapShader_constructor(JNIEnv* env, jobject, const SkBitmap*
///////////////////////////////////////////////////////////////////////////////////////////////
-static SkShader* LinearGradient_create1(JNIEnv* env, jobject,
+static void LinearGradient_destructor(JNIEnv* env, jobject o, SkShader* shader)
+{
+ delete reinterpret_cast<jfloat*>(env->GetIntField(o, gLinearGradientClassInfo.bounds));
+ delete reinterpret_cast<jint*>(env->GetIntField(o, gLinearGradientClassInfo.colors));
+ delete reinterpret_cast<jfloat*>(env->GetIntField(o, gLinearGradientClassInfo.positions));
+}
+
+static SkShader* LinearGradient_create1(JNIEnv* env, jobject o,
float x0, float y0, float x1, float y1,
jintArray colorArray, jfloatArray posArray, int tileMode)
{
@@ -90,15 +104,31 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject,
SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
SkScalar* pos = NULL;
-
+
+ jfloat* storedBounds = new jfloat[4];
+ storedBounds[0] = x0; storedBounds[1] = y0;
+ storedBounds[2] = x1; storedBounds[3] = y1;
+ jfloat* storedPositions = new jfloat[count];
+ jint* storedColors = new jint[count];
+ memcpy(storedColors, colorValues, count);
+
if (posArray) {
AutoJavaFloatArray autoPos(env, posArray, count);
const float* posValues = autoPos.ptr();
pos = (SkScalar*)storage.get();
- for (size_t i = 0; i < count; i++)
+ for (size_t i = 0; i < count; i++) {
pos[i] = SkFloatToScalar(posValues[i]);
+ storedPositions[i] = posValues[i];
+ }
+ } else {
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
}
-
+
+ env->SetIntField(o, gLinearGradientClassInfo.bounds, reinterpret_cast<jint>(storedBounds));
+ env->SetIntField(o, gLinearGradientClassInfo.colors, reinterpret_cast<jint>(storedColors));
+ env->SetIntField(o, gLinearGradientClassInfo.positions, reinterpret_cast<jint>(storedPositions));
+
SkShader* shader = SkGradientShader::CreateLinear(pts,
reinterpret_cast<const SkColor*>(colorValues),
pos, count,
@@ -109,7 +139,7 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject,
return shader;
}
-static SkShader* LinearGradient_create2(JNIEnv* env, jobject,
+static SkShader* LinearGradient_create2(JNIEnv* env, jobject o,
float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode)
{
@@ -120,6 +150,22 @@ static SkShader* LinearGradient_create2(JNIEnv* env, jobject,
SkColor colors[2];
colors[0] = color0;
colors[1] = color1;
+
+ float* storedBounds = new float[4];
+ storedBounds[0] = x0; storedBounds[1] = y0;
+ storedBounds[2] = x1; storedBounds[3] = y1;
+
+ float* storedPositions = new float[2];
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+
+ uint32_t* storedColors = new uint32_t[2];
+ storedColors[0] = color0;
+ storedColors[1] = color1;
+
+ env->SetIntField(o, gLinearGradientClassInfo.bounds, reinterpret_cast<jint>(storedBounds));
+ env->SetIntField(o, gLinearGradientClassInfo.colors, reinterpret_cast<jint>(storedColors));
+ env->SetIntField(o, gLinearGradientClassInfo.positions, reinterpret_cast<jint>(storedPositions));
SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
ThrowIAE_IfNull(env, s);
@@ -254,8 +300,9 @@ static JNINativeMethod gBitmapShaderMethods[] = {
};
static JNINativeMethod gLinearGradientMethods[] = {
- { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 },
- { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }
+ { "nativeDestructor", "(I)V", (void*)LinearGradient_destructor },
+ { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 },
+ { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }
};
static JNINativeMethod gRadialGradientMethods[] = {
@@ -278,6 +325,15 @@ static JNINativeMethod gComposeShaderMethods[] = {
#define REG(env, name, array) \
result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \
if (result < 0) return result
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldType) \
+ var = env->GetFieldID(clazz, fieldName, fieldType); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
int register_android_graphics_Shader(JNIEnv* env);
int register_android_graphics_Shader(JNIEnv* env)
@@ -292,6 +348,11 @@ int register_android_graphics_Shader(JNIEnv* env)
REG(env, "android/graphics/SweepGradient", gSweepGradientMethods);
REG(env, "android/graphics/ComposeShader", gComposeShaderMethods);
+ FIND_CLASS(gLinearGradientClassInfo.clazz, "android/graphics/LinearGradient");
+ GET_FIELD_ID(gLinearGradientClassInfo.bounds, gLinearGradientClassInfo.clazz, "bounds", "I");
+ GET_FIELD_ID(gLinearGradientClassInfo.colors, gLinearGradientClassInfo.clazz, "colors", "I");
+ GET_FIELD_ID(gLinearGradientClassInfo.positions, gLinearGradientClassInfo.clazz, "positions", "I");
+
return result;
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index e5aa5dd..f952702 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -201,7 +201,6 @@ static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject canv
static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray chunks,
float left, float top, float right, float bottom, SkPaint* paint) {
-
jbyte* storage = env->GetByteArrayElements(chunks, NULL);
Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(storage);
Res_png_9patch::deserialize(patch);
@@ -239,6 +238,13 @@ static void android_view_GLES20Canvas_setupBitmapShader(JNIEnv* env, jobject can
(shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
}
+static void android_view_GLES20Canvas_setupLinearShader(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, SkShader* shader, float* bounds, uint32_t* colors,
+ float* positions, SkShader::TileMode tileMode, SkMatrix* matrix) {
+ renderer->setupLinearGradientShader(bounds, colors, positions, tileMode, matrix,
+ (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+}
+
// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -280,6 +286,7 @@ static JNINativeMethod gMethods[] = {
{ "nResetShader", "(I)V", (void*) android_view_GLES20Canvas_resetShader },
{ "nSetupBitmapShader", "(IIIIII)V", (void*) android_view_GLES20Canvas_setupBitmapShader },
+ { "nSetupLinearShader", "(IIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader },
{ "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
(void*) android_view_GLES20Canvas_getClipBounds },
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index e3db105..172e19b 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -17,6 +17,27 @@
package android.graphics;
public class LinearGradient extends Shader {
+ /**
+ * These fields are manipulated by the JNI layer, don't touch!
+ * @hide
+ */
+ public int bounds;
+ /**
+ * @hide
+ */
+ public int colors;
+ /**
+ * @hide
+ */
+ public int positions;
+ /**
+ * @hide
+ */
+ public int count;
+ /**
+ * @hide
+ */
+ public int tileMode;
/** Create a shader that draws a linear gradient along a line.
@param x0 The x-coordinate for the start of the gradient line
@@ -38,6 +59,8 @@ public class LinearGradient extends Shader {
throw new IllegalArgumentException("color and position arrays must be of equal length");
}
native_instance = nativeCreate1(x0, y0, x1, y1, colors, positions, tile.nativeInt);
+ count = colors.length;
+ tileMode = tile.nativeInt;
}
/** Create a shader that draws a linear gradient along a line.
@@ -52,12 +75,18 @@ public class LinearGradient extends Shader {
public LinearGradient(float x0, float y0, float x1, float y1,
int color0, int color1, TileMode tile) {
native_instance = nativeCreate2(x0, y0, x1, y1, color0, color1, tile.nativeInt);
+ count = 2;
+ tileMode = tile.nativeInt;
+ }
+
+ protected void finalize() throws Throwable {
+ super.finalize();
+ nativeDestructor(native_instance);
}
-
- private static native int nativeCreate1(float x0, float y0, float x1, float y1,
- int colors[], float positions[], int tileMode);
- private static native int nativeCreate2(float x0, float y0, float x1, float y1,
- int color0, int color1, int tileMode);
+ private native void nativeDestructor(int native_shader);
+ private native int nativeCreate1(float x0, float y0, float x1, float y1,
+ int colors[], float positions[], int tileMode);
+ private native int nativeCreate2(float x0, float y0, float x1, float y1,
+ int color0, int color1, int tileMode);
}
-
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0bf0e89..1431563 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -528,7 +528,7 @@ void OpenGLRenderer::resetShader() {
void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tileX,
SkShader::TileMode tileY, SkMatrix* matrix, bool hasAlpha) {
- mShader = kShaderBitmap;
+ mShader = OpenGLRenderer::kShaderBitmap;
mShaderBlend = hasAlpha;
mShaderBitmap = bitmap;
mShaderTileX = tileX;
@@ -536,6 +536,18 @@ void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tile
mShaderMatrix = matrix;
}
+void OpenGLRenderer::setupLinearGradientShader(float* bounds, uint32_t* colors,
+ float* positions, SkShader::TileMode tileMode, SkMatrix* matrix, bool hasAlpha) {
+ mShader = OpenGLRenderer::kShaderLinearGradient;
+ mShaderBlend = hasAlpha;
+ mShaderTileX = tileMode;
+ mShaderTileY = tileMode;
+ mShaderMatrix = matrix;
+ mShaderBounds = bounds;
+ mShaderColors = colors;
+ mShaderPositions = positions;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Drawing implementation
///////////////////////////////////////////////////////////////////////////////
@@ -555,9 +567,12 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
const GLfloat b = a * ((color ) & 0xFF) / 255.0f;
switch (mShader) {
- case kShaderBitmap:
+ case OpenGLRenderer::kShaderBitmap:
drawBitmapShader(left, top, right, bottom, a, mode);
return;
+ case OpenGLRenderer::kShaderLinearGradient:
+ // TODO: Generate gradient texture, set appropriate shader
+ break;
default:
break;
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 235931c..b3cef88 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -103,6 +103,8 @@ public:
void resetShader();
void setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tileX, SkShader::TileMode tileY,
SkMatrix* matrix, bool hasAlpha);
+ void setupLinearGradientShader(float* bounds, uint32_t* colors, float* positions,
+ SkShader::TileMode tileMode, SkMatrix* matrix, bool hasAlpha);
private:
/**
@@ -319,13 +321,18 @@ private:
GLenum mLastSrcMode;
GLenum mLastDstMode;
- // Skia shader
+ // Skia shaders
ShaderType mShader;
bool mShaderBlend;
- SkBitmap* mShaderBitmap;
SkShader::TileMode mShaderTileX;
SkShader::TileMode mShaderTileY;
SkMatrix* mShaderMatrix;
+ // Bitmaps
+ SkBitmap* mShaderBitmap;
+ // Gradients
+ float* mShaderBounds;
+ uint32_t* mShaderColors;
+ float* mShaderPositions;
// Various caches
TextureCache mTextureCache;
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 96dfab9..3316c7e 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -90,22 +90,22 @@ public:
transform.mapRect(r);
switch (op) {
- case SkRegion::kDifference_Op:
- break;
- case SkRegion::kIntersect_Op:
- clipped = clipRect.intersect(r);
- break;
- case SkRegion::kUnion_Op:
- clipped = clipRect.unionWith(r);
- break;
- case SkRegion::kXOR_Op:
- break;
- case SkRegion::kReverseDifference_Op:
- break;
- case SkRegion::kReplace_Op:
- clipRect.set(r);
- clipped = true;
- break;
+ case SkRegion::kDifference_Op:
+ break;
+ case SkRegion::kIntersect_Op:
+ clipped = clipRect.intersect(r);
+ break;
+ case SkRegion::kUnion_Op:
+ clipped = clipRect.unionWith(r);
+ break;
+ case SkRegion::kXOR_Op:
+ break;
+ case SkRegion::kReverseDifference_Op:
+ break;
+ case SkRegion::kReplace_Op:
+ clipRect.set(r);
+ clipped = true;
+ break;
}
if (clipped) {