Merge "Add plumbing to support gradients in OpenGL renderer."
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user