From db1938e0e6ef816e228c815adccebd5cb05f2aa8 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 2 Aug 2010 18:50:22 -0700 Subject: Add support for ColorFilters. Color filters are fully supported and can be used with shaders. Change-Id: Id90ccf1c81cb462f2431f366f3f8f710d7971e04 --- core/java/android/view/GLES20Canvas.java | 60 +++++++++++++++++++++------- core/jni/android/graphics/ColorFilter.cpp | 65 ++++++++++++++++++++++--------- core/jni/android_view_GLES20Canvas.cpp | 14 +++++-- 3 files changed, 103 insertions(+), 36 deletions(-) (limited to 'core') diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 21e6793..63a0c4c 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -18,6 +18,7 @@ package android.view; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.ColorFilter; import android.graphics.DrawFilter; import android.graphics.Matrix; import android.graphics.Paint; @@ -376,9 +377,11 @@ class GLES20Canvas extends Canvas { @Override public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) { // Shaders are ignored when drawing patches + boolean hasColorFilter = paint != null && setupColorFilter(paint); final int nativePaint = paint == null ? 0 : paint.mNativePaint; nDrawPatch(mRenderer, bitmap.mNativeBitmap, chunks, dst.left, dst.top, dst.right, dst.bottom, nativePaint); + if (hasColorFilter) nResetModifiers(mRenderer); } private native void nDrawPatch(int renderer, int bitmap, byte[] chunks, float left, float top, @@ -387,8 +390,10 @@ class GLES20Canvas extends Canvas { @Override public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { // Shaders are ignored when drawing bitmaps + boolean hasColorFilter = paint != null && setupColorFilter(paint); final int nativePaint = paint == null ? 0 : paint.mNativePaint; nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint); + if (hasColorFilter) nResetModifiers(mRenderer); } private native void nDrawBitmap(int renderer, int bitmap, float left, float top, int paint); @@ -396,8 +401,10 @@ class GLES20Canvas extends Canvas { @Override public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { // Shaders are ignored when drawing bitmaps + boolean hasColorFilter = paint != null && setupColorFilter(paint); final int nativePaint = paint == null ? 0 : paint.mNativePaint; nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint); + if (hasColorFilter) nResetModifiers(mRenderer); } private native void nDrawBitmap(int renderer, int bitmap, int matrix, int paint); @@ -405,6 +412,7 @@ class GLES20Canvas extends Canvas { @Override public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { // Shaders are ignored when drawing bitmaps + boolean hasColorFilter = paint != null && setupColorFilter(paint); final int nativePaint = paint == null ? 0 : paint.mNativePaint; int left, top, right, bottom; @@ -421,14 +429,17 @@ class GLES20Canvas extends Canvas { nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint); + if (hasColorFilter) nResetModifiers(mRenderer); } @Override public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { // Shaders are ignored when drawing bitmaps + boolean hasColorFilter = paint != null && setupColorFilter(paint); final int nativePaint = paint == null ? 0 : paint.mNativePaint; nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint); + if (hasColorFilter) nResetModifiers(mRenderer); } private native void nDrawBitmap(int renderer, int bitmap, @@ -439,11 +450,13 @@ class GLES20Canvas extends Canvas { public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, Paint paint) { // Shaders are ignored when drawing bitmaps + boolean hasColorFilter = paint != null && setupColorFilter(paint); final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config); final int nativePaint = paint == null ? 0 : paint.mNativePaint; nDrawBitmap(mRenderer, b.mNativeBitmap, x, y, nativePaint); b.recycle(); + if (hasColorFilter) nResetModifiers(mRenderer); } @Override @@ -556,9 +569,9 @@ class GLES20Canvas extends Canvas { @Override public void drawRect(float left, float top, float right, float bottom, Paint paint) { - boolean hasShader = setupShader(paint); + boolean hasModifier = setupModifiers(paint); nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint); - if (hasShader) nResetShader(mRenderer); + if (hasModifier) nResetModifiers(mRenderer); } private native void nDrawRect(int renderer, float left, float top, float right, float bottom, @@ -589,9 +602,9 @@ class GLES20Canvas extends Canvas { if ((index | count | (index + count) | (text.length - index - count)) < 0) { throw new IndexOutOfBoundsException(); } - boolean hasShader = setupShader(paint); + boolean hasModifier = setupModifiers(paint); nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); - if (hasShader) nResetShader(mRenderer); + if (hasModifier) nResetModifiers(mRenderer); } private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y, @@ -599,7 +612,7 @@ class GLES20Canvas extends Canvas { @Override public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { - boolean hasShader = setupShader(paint); + boolean hasModifier = setupModifiers(paint); if (text instanceof String || text instanceof SpannedString || text instanceof SpannableString) { nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, @@ -613,7 +626,7 @@ class GLES20Canvas extends Canvas { nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint); TemporaryBuffer.recycle(buf); } - if (hasShader) nResetShader(mRenderer); + if (hasModifier) nResetModifiers(mRenderer); } @Override @@ -621,9 +634,9 @@ class GLES20Canvas extends Canvas { if ((start | end | (end - start) | (text.length() - end)) < 0) { throw new IndexOutOfBoundsException(); } - boolean hasShader = setupShader(paint); + boolean hasModifier = setupModifiers(paint); nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); - if (hasShader) nResetShader(mRenderer); + if (hasModifier) nResetModifiers(mRenderer); } private native void nDrawText(int renderer, String text, int start, int end, float x, float y, @@ -631,9 +644,9 @@ class GLES20Canvas extends Canvas { @Override public void drawText(String text, float x, float y, Paint paint) { - boolean hasShader = setupShader(paint); + boolean hasModifier = setupModifiers(paint); nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint); - if (hasShader) nResetShader(mRenderer); + if (hasModifier) nResetModifiers(mRenderer); } @Override @@ -666,15 +679,34 @@ class GLES20Canvas extends Canvas { // TODO: Implement } - private boolean setupShader(Paint paint) { + private boolean setupModifiers(Paint paint) { + boolean hasModifier = false; + final Shader shader = paint.getShader(); if (shader != null) { nSetupShader(mRenderer, shader.native_shader); + hasModifier = true; + } + + final ColorFilter filter = paint.getColorFilter(); + if (filter != null) { + nSetupColorFilter(mRenderer, filter.nativeColorFilter); + hasModifier = true; + } + + return hasModifier; + } + + private boolean setupColorFilter(Paint paint) { + final ColorFilter filter = paint.getColorFilter(); + if (filter != null) { + nSetupColorFilter(mRenderer, filter.nativeColorFilter); return true; } - return false; + return false; } - + private native void nSetupShader(int renderer, int shader); - private native void nResetShader(int renderer); + private native void nSetupColorFilter(int renderer, int colorFilter); + private native void nResetModifiers(int renderer); } diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp index ebfb209..848234f 100644 --- a/core/jni/android/graphics/ColorFilter.cpp +++ b/core/jni/android/graphics/ColorFilter.cpp @@ -23,28 +23,38 @@ #include "SkColorMatrixFilter.h" #include "SkPorterDuff.h" +#include + namespace android { +using namespace uirenderer; + class SkColorFilterGlue { public: - - static void finalizer(JNIEnv* env, jobject clazz, SkColorFilter* obj) { + static void finalizer(JNIEnv* env, jobject clazz, SkColorFilter* obj, SkiaColorFilter* f) { + delete f; obj->safeUnref(); } - static SkColorFilter* CreatePorterDuffFilter(JNIEnv* env, jobject, - jint srcColor, SkPorterDuff::Mode mode) { - return SkColorFilter::CreateModeFilter(srcColor, - SkPorterDuff::ToXfermodeMode(mode)); + static SkColorFilter* CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, + SkPorterDuff::Mode mode) { + return SkColorFilter::CreateModeFilter(srcColor, SkPorterDuff::ToXfermodeMode(mode)); } - static SkColorFilter* CreateLightingFilter(JNIEnv* env, jobject, - jint mul, jint add) { + static SkiaColorFilter* glCreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, + SkPorterDuff::Mode mode) { + return new SkiaBlendFilter(srcColor, SkPorterDuff::ToXfermodeMode(mode)); + } + + static SkColorFilter* CreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) { return SkColorFilter::CreateLightingFilter(mul, add); } - static SkColorFilter* CreateColorMatrixFilter(JNIEnv* env, jobject, - jfloatArray jarray) { + static SkiaColorFilter* glCreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) { + return new SkiaLightingFilter(mul, add); + } + + static SkColorFilter* CreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) { AutoJavaFloatArray autoArray(env, jarray, 20); const float* src = autoArray.ptr(); @@ -58,26 +68,44 @@ public: return new SkColorMatrixFilter(src); #endif } - + + static SkiaColorFilter* glCreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) { + AutoJavaFloatArray autoArray(env, jarray, 20); + const float* src = autoArray.ptr(); + + float* colorMatrix = new float[16]; + memcpy(colorMatrix, src, 4 * sizeof(float)); + memcpy(&colorMatrix[4], &src[5], 4 * sizeof(float)); + memcpy(&colorMatrix[8], &src[10], 4 * sizeof(float)); + memcpy(&colorMatrix[12], &src[15], 4 * sizeof(float)); + + float* colorVector = new float[4]; + colorVector[0] = src[4]; + colorVector[1] = src[9]; + colorVector[2] = src[14]; + colorVector[3] = src[19]; + + return new SkiaColorMatrixFilter(colorMatrix, colorVector); + } }; static JNINativeMethod colorfilter_methods[] = { - {"finalizer", "(I)V", (void*) SkColorFilterGlue::finalizer} + {"finalizer", "(II)V", (void*) SkColorFilterGlue::finalizer} }; static JNINativeMethod porterduff_methods[] = { - {"native_CreatePorterDuffFilter","(II)I", - (void*) SkColorFilterGlue::CreatePorterDuffFilter} + { "native_CreatePorterDuffFilter", "(II)I", (void*) SkColorFilterGlue::CreatePorterDuffFilter }, + { "nCreatePorterDuffFilter", "(II)I", (void*) SkColorFilterGlue::glCreatePorterDuffFilter } }; static JNINativeMethod lighting_methods[] = { - {"native_CreateLightingFilter","(II)I", - (void*) SkColorFilterGlue::CreateLightingFilter} + { "native_CreateLightingFilter", "(II)I", (void*) SkColorFilterGlue::CreateLightingFilter }, + { "nCreateLightingFilter", "(II)I", (void*) SkColorFilterGlue::glCreateLightingFilter }, }; static JNINativeMethod colormatrix_methods[] = { - {"nativeColorMatrixFilter","([F)I", - (void*) SkColorFilterGlue::CreateColorMatrixFilter} + { "nativeColorMatrixFilter", "([F)I", (void*) SkColorFilterGlue::CreateColorMatrixFilter }, + { "nColorMatrixFilter", "([F)I", (void*) SkColorFilterGlue::glCreateColorMatrixFilter } }; #define REG(env, name, array) \ @@ -85,7 +113,6 @@ static JNINativeMethod colormatrix_methods[] = { SK_ARRAY_COUNT(array)); \ if (result < 0) return result - int register_android_graphics_ColorFilter(JNIEnv* env) { int result; diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index ece9636..142e194 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -228,12 +229,13 @@ static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject canvas, } // ---------------------------------------------------------------------------- -// Shaders +// Shaders and color filters // ---------------------------------------------------------------------------- -static void android_view_GLES20Canvas_resetShader(JNIEnv* env, jobject canvas, +static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer) { renderer->resetShader(); + renderer->resetColorFilter(); } static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject canvas, @@ -241,6 +243,11 @@ static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject canvas, renderer->setupShader(shader); } +static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, SkiaColorFilter* filter) { + renderer->setupColorFilter(filter); +} + // ---------------------------------------------------------------------------- // Text // ---------------------------------------------------------------------------- @@ -311,8 +318,9 @@ static JNINativeMethod gMethods[] = { { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor }, { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, - { "nResetShader", "(I)V", (void*) android_view_GLES20Canvas_resetShader }, + { "nResetModifiers", "(I)V", (void*) android_view_GLES20Canvas_resetModifiers }, { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader }, + { "nSetupColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setupColorFilter }, { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray }, { "nDrawText", "(ILjava/lang/String;IIFFII)V", -- cgit v1.1