Add support for ColorFilters.
Color filters are fully supported and can be used with shaders. Change-Id: Id90ccf1c81cb462f2431f366f3f8f710d7971e04
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -23,28 +23,38 @@
|
||||
#include "SkColorMatrixFilter.h"
|
||||
#include "SkPorterDuff.h"
|
||||
|
||||
#include <SkiaColorFilter.h>
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <OpenGLRenderer.h>
|
||||
#include <SkiaShader.h>
|
||||
#include <SkiaColorFilter.h>
|
||||
#include <Rect.h>
|
||||
#include <ui/Rect.h>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -23,12 +23,20 @@ package android.graphics;
|
||||
|
||||
|
||||
public class ColorFilter {
|
||||
int native_instance;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int nativeColorFilter;
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
finalizer(native_instance);
|
||||
try {
|
||||
super.finalize();
|
||||
} finally {
|
||||
finalizer(native_instance, nativeColorFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private static native void finalizer(int native_instance);
|
||||
|
||||
int native_instance;
|
||||
private static native void finalizer(int native_instance, int nativeColorFilter);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ public class ColorMatrixColorFilter extends ColorFilter {
|
||||
* is constructed will not be reflected in the filter.
|
||||
*/
|
||||
public ColorMatrixColorFilter(ColorMatrix matrix) {
|
||||
native_instance = nativeColorMatrixFilter(matrix.getArray());
|
||||
final float[] colorMatrix = matrix.getArray();
|
||||
native_instance = nativeColorMatrixFilter(colorMatrix);
|
||||
nativeColorFilter = nColorMatrixFilter(colorMatrix);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,7 +42,9 @@ public class ColorMatrixColorFilter extends ColorFilter {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
native_instance = nativeColorMatrixFilter(array);
|
||||
nativeColorFilter = nColorMatrixFilter(array);
|
||||
}
|
||||
|
||||
private static native int nativeColorMatrixFilter(float[] array);
|
||||
private static native int nColorMatrixFilter(float[] array);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@ public class LightingColorFilter extends ColorFilter {
|
||||
*/
|
||||
public LightingColorFilter(int mul, int add) {
|
||||
native_instance = native_CreateLightingFilter(mul, add);
|
||||
nativeColorFilter = nCreateLightingFilter(mul, add);
|
||||
}
|
||||
|
||||
private static native int native_CreateLightingFilter(int mul, int add);
|
||||
private static native int nCreateLightingFilter(int mul, int add);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ public class PorterDuffColorFilter extends ColorFilter {
|
||||
* @param mode The porter-duff mode that is applied
|
||||
*/
|
||||
public PorterDuffColorFilter(int srcColor, PorterDuff.Mode mode) {
|
||||
native_instance = native_CreatePorterDuffFilter(srcColor,
|
||||
mode.nativeInt);
|
||||
native_instance = native_CreatePorterDuffFilter(srcColor, mode.nativeInt);
|
||||
nativeColorFilter = nCreatePorterDuffFilter(srcColor, mode.nativeInt);
|
||||
}
|
||||
|
||||
private static native int native_CreatePorterDuffFilter(int srcColor,
|
||||
int porterDuffMode);
|
||||
private static native int native_CreatePorterDuffFilter(int srcColor, int porterDuffMode);
|
||||
private static native int nCreatePorterDuffFilter(int srcColor, int porterDuffMode);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ LOCAL_SRC_FILES:= \
|
||||
PatchCache.cpp \
|
||||
Program.cpp \
|
||||
ProgramCache.cpp \
|
||||
SkiaColorFilter.cpp \
|
||||
SkiaShader.cpp \
|
||||
TextureCache.cpp
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "OpenGLRenderer"
|
||||
|
||||
#ifndef ANDROID_UI_EXTENSIONS_H
|
||||
#define ANDROID_UI_EXTENSIONS_H
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ OpenGLRenderer::OpenGLRenderer():
|
||||
|
||||
mCurrentProgram = NULL;
|
||||
mShader = NULL;
|
||||
mColorFilter = NULL;
|
||||
|
||||
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
|
||||
|
||||
@@ -460,7 +461,6 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
|
||||
const float u2 = srcRight / width;
|
||||
const float v2 = srcBottom / height;
|
||||
|
||||
// TODO: Do this in the shader
|
||||
resetDrawTextureTexCoords(u1, v1, u2, v2);
|
||||
|
||||
drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
|
||||
@@ -552,6 +552,8 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
mModelView.loadIdentity();
|
||||
|
||||
GLuint textureUnit = 0;
|
||||
// Needs to be set prior to calling FontRenderer::getTexture()
|
||||
glActiveTexture(gTextureUnits[textureUnit]);
|
||||
|
||||
ProgramDescription description;
|
||||
description.hasTexture = true;
|
||||
@@ -559,10 +561,14 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
if (mShader) {
|
||||
mShader->describe(description, mExtensions);
|
||||
}
|
||||
if (mColorFilter) {
|
||||
mColorFilter->describe(description, mExtensions);
|
||||
}
|
||||
|
||||
useProgram(mProgramCache.get(description));
|
||||
mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
|
||||
|
||||
// Text is always blended, no need to check the shader
|
||||
chooseBlending(true, mode);
|
||||
bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit);
|
||||
glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit);
|
||||
@@ -578,6 +584,9 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
if (mShader) {
|
||||
mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
|
||||
}
|
||||
if (mColorFilter) {
|
||||
mColorFilter->setupProgram(mCurrentProgram);
|
||||
}
|
||||
|
||||
// TODO: Implement scale properly
|
||||
const Rect& clip = mSnapshot->getLocalClip();
|
||||
@@ -603,6 +612,18 @@ void OpenGLRenderer::setupShader(SkiaShader* shader) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Color filters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::resetColorFilter() {
|
||||
mColorFilter = NULL;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) {
|
||||
mColorFilter = filter;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Drawing implementation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -631,6 +652,9 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
|
||||
if (mShader) {
|
||||
mShader->describe(description, mExtensions);
|
||||
}
|
||||
if (mColorFilter) {
|
||||
mColorFilter->describe(description, mExtensions);
|
||||
}
|
||||
|
||||
// Build and use the appropriate shader
|
||||
useProgram(mProgramCache.get(description));
|
||||
@@ -654,6 +678,9 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
|
||||
if (mShader) {
|
||||
mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
|
||||
}
|
||||
if (mColorFilter) {
|
||||
mColorFilter->setupProgram(mCurrentProgram);
|
||||
}
|
||||
|
||||
// Draw the mesh
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
|
||||
@@ -680,6 +707,9 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
|
||||
GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) {
|
||||
ProgramDescription description;
|
||||
description.hasTexture = true;
|
||||
if (mColorFilter) {
|
||||
mColorFilter->describe(description, mExtensions);
|
||||
}
|
||||
|
||||
mModelView.loadTranslate(left, top, 0.0f);
|
||||
mModelView.scale(right - left, bottom - top, 1.0f);
|
||||
@@ -703,6 +733,11 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
|
||||
gMeshStride, vertices);
|
||||
glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
|
||||
|
||||
// Color filter
|
||||
if (mColorFilter) {
|
||||
mColorFilter->setupProgram(mCurrentProgram);
|
||||
}
|
||||
|
||||
if (!indices) {
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
|
||||
} else {
|
||||
@@ -712,8 +747,6 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
|
||||
}
|
||||
|
||||
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) {
|
||||
// In theory we should not blend if the mode is Src, but it's rare enough
|
||||
// that it's not worth it
|
||||
blend = blend || mode != SkXfermode::kSrcOver_Mode;
|
||||
if (blend) {
|
||||
if (!mBlend) {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "FontRenderer.h"
|
||||
#include "ProgramCache.h"
|
||||
#include "SkiaShader.h"
|
||||
#include "SkiaColorFilter.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -95,6 +96,9 @@ public:
|
||||
void resetShader();
|
||||
void setupShader(SkiaShader* shader);
|
||||
|
||||
void resetColorFilter();
|
||||
void setupColorFilter(SkiaColorFilter* filter);
|
||||
|
||||
void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
|
||||
|
||||
private:
|
||||
@@ -281,6 +285,9 @@ private:
|
||||
Program* mCurrentProgram;
|
||||
SkiaShader* mShader;
|
||||
|
||||
// Color filters
|
||||
SkiaColorFilter* mColorFilter;
|
||||
|
||||
// Used to draw textured quads
|
||||
TextureVertex mMeshVertices[4];
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@ namespace uirenderer {
|
||||
// Vertex shaders snippets
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: Implement BitmapShader, implement repeat/mirror for npot
|
||||
|
||||
const char* gVS_Header_Attributes =
|
||||
"attribute vec4 position;\n";
|
||||
const char* gVS_Header_Attributes_TexCoords =
|
||||
@@ -85,10 +83,10 @@ const char* gFS_Uniforms_ColorOp[4] = {
|
||||
"uniform mat4 colorMatrix;\n"
|
||||
"uniform vec4 colorMatrixVector;\n",
|
||||
// Lighting
|
||||
"uniform float lightingMul;\n"
|
||||
"uniform float lightingAdd;\n",
|
||||
"uniform vec4 lightingMul;\n"
|
||||
"uniform vec4 lightingAdd;\n",
|
||||
// PorterDuff
|
||||
"uniform vec4 colorBLend;\n"
|
||||
"uniform vec4 colorBlend;\n"
|
||||
};
|
||||
const char* gFS_Main =
|
||||
"\nvoid main(void) {\n"
|
||||
@@ -121,11 +119,14 @@ const char* gFS_Main_ApplyColorOp[4] = {
|
||||
// None
|
||||
"",
|
||||
// Matrix
|
||||
// TODO: Fix premultiplied alpha computations for color matrix
|
||||
" fragColor *= colorMatrix;\n"
|
||||
" fragColor += colorMatrixVector;\n",
|
||||
" fragColor += colorMatrixVector;\n"
|
||||
" fragColor.rgb *= fragColor.a;\n",
|
||||
// Lighting
|
||||
" fragColor *= lightingMul;\n"
|
||||
" fragColor += lightingAdd;\n",
|
||||
" float lightingAlpha = fragColor.a;\n"
|
||||
" fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n"
|
||||
" fragColor.a = lightingAlpha;\n",
|
||||
// PorterDuff
|
||||
" fragColor = blendColors(colorBlend, fragColor);\n"
|
||||
};
|
||||
@@ -345,7 +346,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
|
||||
// End the shader
|
||||
shader.append(gFS_Footer);
|
||||
|
||||
PROGRAM_LOGD("*** Generated fragment shader:\n\n%s", shader.string());
|
||||
if (DEBUG_PROGRAM_CACHE) {
|
||||
PROGRAM_LOGD("*** Generated fragment shader:\n\n");
|
||||
printLongString(shader);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
@@ -391,5 +396,19 @@ void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wra
|
||||
shader.append("}\n");
|
||||
}
|
||||
|
||||
void ProgramCache::printLongString(const String8& shader) const {
|
||||
ssize_t index = 0;
|
||||
ssize_t lastIndex = 0;
|
||||
const char* str = shader.string();
|
||||
while ((index = shader.find("\n", index)) > -1) {
|
||||
String8 line(str, index - lastIndex);
|
||||
if (line.length() == 0) line.append("\n");
|
||||
PROGRAM_LOGD("%s", line.string());
|
||||
index++;
|
||||
str += (index - lastIndex);
|
||||
lastIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace uirenderer {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Debug
|
||||
#define DEBUG_PROGRAM_CACHE 1
|
||||
#define DEBUG_PROGRAM_CACHE 0
|
||||
|
||||
// Debug
|
||||
#if DEBUG_PROGRAM_CACHE
|
||||
@@ -180,6 +180,8 @@ private:
|
||||
void generatePorterDuffBlend(String8& shader, const char* name, SkXfermode::Mode mode);
|
||||
void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
|
||||
|
||||
void printLongString(const String8& shader) const;
|
||||
|
||||
KeyedVector<programid, Program*> mCache;
|
||||
|
||||
}; // class ProgramCache
|
||||
|
||||
102
libs/hwui/SkiaColorFilter.cpp
Normal file
102
libs/hwui/SkiaColorFilter.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "SkiaColorFilter.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Base color filter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkiaColorFilter::SkiaColorFilter(Type type, bool blend): mType(type), mBlend(blend) {
|
||||
}
|
||||
|
||||
SkiaColorFilter::~SkiaColorFilter() {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Color matrix filter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkiaColorMatrixFilter::SkiaColorMatrixFilter(float* matrix, float* vector):
|
||||
SkiaColorFilter(kColorMatrix, true), mMatrix(matrix), mVector(vector) {
|
||||
}
|
||||
|
||||
SkiaColorMatrixFilter::~SkiaColorMatrixFilter() {
|
||||
delete[] mMatrix;
|
||||
delete[] mVector;
|
||||
}
|
||||
|
||||
void SkiaColorMatrixFilter::describe(ProgramDescription& description,
|
||||
const Extensions& extensions) {
|
||||
description.colorOp = ProgramDescription::kColorMatrix;
|
||||
}
|
||||
|
||||
void SkiaColorMatrixFilter::setupProgram(Program* program) {
|
||||
glUniformMatrix4fv(program->getUniform("colorMatrix"), 1, GL_FALSE, &mMatrix[0]);
|
||||
glUniform4fv(program->getUniform("colorMatrixVector"), 1, mVector);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Lighting color filter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkiaLightingFilter::SkiaLightingFilter(int multiply, int add):
|
||||
SkiaColorFilter(kLighting, true) {
|
||||
mMulR = ((multiply >> 16) & 0xFF) / 255.0f;
|
||||
mMulG = ((multiply >> 8) & 0xFF) / 255.0f;
|
||||
mMulB = ((multiply ) & 0xFF) / 255.0f;
|
||||
|
||||
mAddR = ((add >> 16) & 0xFF) / 255.0f;
|
||||
mAddG = ((add >> 8) & 0xFF) / 255.0f;
|
||||
mAddB = ((add ) & 0xFF) / 255.0f;
|
||||
}
|
||||
|
||||
void SkiaLightingFilter::describe(ProgramDescription& description, const Extensions& extensions) {
|
||||
description.colorOp = ProgramDescription::kColorLighting;
|
||||
}
|
||||
|
||||
void SkiaLightingFilter::setupProgram(Program* program) {
|
||||
glUniform4f(program->getUniform("lightingMul"), mMulR, mMulG, mMulB, 1.0f);
|
||||
glUniform4f(program->getUniform("lightingAdd"), mAddR, mAddG, mAddB, 0.0f);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Blend color filter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkiaBlendFilter::SkiaBlendFilter(int color, SkXfermode::Mode mode):
|
||||
SkiaColorFilter(kBlend, true), mMode(mode) {
|
||||
const int alpha = (color >> 24) & 0xFF;
|
||||
mA = alpha / 255.0f;
|
||||
mR = mA * ((color >> 16) & 0xFF) / 255.0f;
|
||||
mG = mA * ((color >> 8) & 0xFF) / 255.0f;
|
||||
mB = mA * ((color ) & 0xFF) / 255.0f;
|
||||
}
|
||||
|
||||
void SkiaBlendFilter::describe(ProgramDescription& description, const Extensions& extensions) {
|
||||
description.colorOp = ProgramDescription::kColorBlend;
|
||||
description.colorMode = mMode;
|
||||
}
|
||||
|
||||
void SkiaBlendFilter::setupProgram(Program* program) {
|
||||
glUniform4f(program->getUniform("colorBlend"), mR, mG, mB, mA);
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
118
libs/hwui/SkiaColorFilter.h
Normal file
118
libs/hwui/SkiaColorFilter.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_UI_SKIA_COLOR_FILTER_H
|
||||
#define ANDROID_UI_SKIA_COLOR_FILTER_H
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "ProgramCache.h"
|
||||
#include "Extensions.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Base color filter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Represents a Skia color filter. A color filter modifies a ProgramDescription
|
||||
* and sets uniforms on the resulting shaders.
|
||||
*/
|
||||
struct SkiaColorFilter {
|
||||
/**
|
||||
* Type of Skia color filter in use.
|
||||
*/
|
||||
enum Type {
|
||||
kNone,
|
||||
kColorMatrix,
|
||||
kLighting,
|
||||
kBlend,
|
||||
};
|
||||
|
||||
SkiaColorFilter(Type type, bool blend);
|
||||
virtual ~SkiaColorFilter();
|
||||
|
||||
virtual void describe(ProgramDescription& description, const Extensions& extensions) = 0;
|
||||
virtual void setupProgram(Program* program) = 0;
|
||||
|
||||
inline bool blend() const {
|
||||
return mBlend;
|
||||
}
|
||||
|
||||
Type type() const {
|
||||
return mType;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type mType;
|
||||
bool mBlend;
|
||||
}; // struct SkiaColorFilter
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* A color filter that multiplies the source color with a matrix and adds a vector.
|
||||
*/
|
||||
struct SkiaColorMatrixFilter: public SkiaColorFilter {
|
||||
SkiaColorMatrixFilter(float* matrix, float* vector);
|
||||
~SkiaColorMatrixFilter();
|
||||
|
||||
void describe(ProgramDescription& description, const Extensions& extensions);
|
||||
void setupProgram(Program* program);
|
||||
|
||||
private:
|
||||
float* mMatrix;
|
||||
float* mVector;
|
||||
}; // struct SkiaColorMatrixFilter
|
||||
|
||||
/**
|
||||
* A color filters that multiplies the source color with a fixed value and adds
|
||||
* another fixed value. Ignores the alpha channel of both arguments.
|
||||
*/
|
||||
struct SkiaLightingFilter: public SkiaColorFilter {
|
||||
SkiaLightingFilter(int multiply, int add);
|
||||
|
||||
void describe(ProgramDescription& description, const Extensions& extensions);
|
||||
void setupProgram(Program* program);
|
||||
|
||||
private:
|
||||
GLfloat mMulR, mMulG, mMulB;
|
||||
GLfloat mAddR, mAddG, mAddB;
|
||||
}; // struct SkiaLightingFilter
|
||||
|
||||
/**
|
||||
* A color filters that blends the source color with a specified destination color
|
||||
* and PorterDuff blending mode.
|
||||
*/
|
||||
struct SkiaBlendFilter: public SkiaColorFilter {
|
||||
SkiaBlendFilter(int color, SkXfermode::Mode mode);
|
||||
|
||||
void describe(ProgramDescription& description, const Extensions& extensions);
|
||||
void setupProgram(Program* program);
|
||||
|
||||
private:
|
||||
SkXfermode::Mode mMode;
|
||||
GLfloat mR, mG, mB, mA;
|
||||
}; // struct SkiaBlendFilter
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_UI_SKIA_COLOR_FILTER_H
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SKIA_SHADER_H
|
||||
#define SKIA_SHADER_H
|
||||
#ifndef ANDROID_UI_SKIA_SHADER_H
|
||||
#define ANDROID_UI_SKIA_SHADER_H
|
||||
|
||||
#include <SkShader.h>
|
||||
#include <SkXfermode.h>
|
||||
@@ -160,4 +160,4 @@ private:
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
#endif // SKIA_SHADER_H
|
||||
#endif // ANDROID_UI_SKIA_SHADER_H
|
||||
|
||||
@@ -133,6 +133,15 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="ColorFiltersActivity"
|
||||
android:label="_ColorFilters">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.test.hwui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public class ColorFiltersActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final BitmapsView view = new BitmapsView(this);
|
||||
setContentView(view);
|
||||
}
|
||||
|
||||
static class BitmapsView extends View {
|
||||
private final Bitmap mBitmap1;
|
||||
private final Bitmap mBitmap2;
|
||||
private final Paint mColorMatrixPaint;
|
||||
private final Paint mLightingPaint;
|
||||
private final Paint mBlendPaint;
|
||||
|
||||
BitmapsView(Context c) {
|
||||
super(c);
|
||||
|
||||
mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
|
||||
mBitmap2 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset2);
|
||||
|
||||
mColorMatrixPaint = new Paint();
|
||||
final ColorMatrix colorMatrix = new ColorMatrix();
|
||||
colorMatrix.setSaturation(0);
|
||||
mColorMatrixPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
|
||||
|
||||
mLightingPaint = new Paint();
|
||||
mLightingPaint.setColorFilter(new LightingColorFilter(0x0060ffff, 0x00101030));
|
||||
|
||||
mBlendPaint = new Paint();
|
||||
mBlendPaint.setColorFilter(new PorterDuffColorFilter(0x7f990040,
|
||||
PorterDuff.Mode.SRC_OVER));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
canvas.drawARGB(255, 255, 255, 255);
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(120.0f, 50.0f);
|
||||
canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mColorMatrixPaint);
|
||||
|
||||
canvas.translate(0.0f, 50.0f + mBitmap1.getHeight());
|
||||
canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mLightingPaint);
|
||||
|
||||
canvas.translate(0.0f, 50.0f + mBitmap1.getHeight());
|
||||
canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBlendPaint);
|
||||
canvas.restore();
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(120.0f + mBitmap1.getWidth() + 120.0f, 50.0f);
|
||||
canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mColorMatrixPaint);
|
||||
|
||||
canvas.translate(0.0f, 50.0f + mBitmap2.getHeight());
|
||||
canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mLightingPaint);
|
||||
|
||||
canvas.translate(0.0f, 50.0f + mBitmap2.getHeight());
|
||||
canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mBlendPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,9 @@ import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ComposeShader;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
@@ -54,6 +56,7 @@ public class MoreShadersActivity extends Activity {
|
||||
private ComposeShader mCompose2Shader;
|
||||
private Paint mLargePaint;
|
||||
private BitmapShader mScaled2Shader;
|
||||
private ColorFilter mColorFilter;
|
||||
|
||||
ShadersView(Context c) {
|
||||
super(c);
|
||||
@@ -87,6 +90,8 @@ public class MoreShadersActivity extends Activity {
|
||||
mCompose2Shader = new ComposeShader(mHorGradient, mScaledShader,
|
||||
PorterDuff.Mode.SRC_OUT);
|
||||
|
||||
mColorFilter = new LightingColorFilter(0x0060ffff, 0x00101030);
|
||||
|
||||
mLargePaint = new Paint();
|
||||
mLargePaint.setAntiAlias(true);
|
||||
mLargePaint.setTextSize(36.0f);
|
||||
@@ -122,7 +127,9 @@ public class MoreShadersActivity extends Activity {
|
||||
canvas.drawText("OpenGL rendering", 0.0f, 60.0f, mLargePaint);
|
||||
|
||||
mLargePaint.setShader(mCompose2Shader);
|
||||
mLargePaint.setColorFilter(mColorFilter);
|
||||
canvas.drawText("OpenGL rendering", 0.0f, 100.0f, mLargePaint);
|
||||
mLargePaint.setColorFilter(null);
|
||||
|
||||
canvas.translate(0.0f, 40.0f + mDrawHeight);
|
||||
mLargePaint.setShader(mVertGradient);
|
||||
|
||||
Reference in New Issue
Block a user