Loading core/java/android/view/GLES20Canvas.java +11 −23 Original line number Diff line number Diff line Loading @@ -17,21 +17,17 @@ package android.view; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.DrawFilter; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Picture; import android.graphics.PorterDuff; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; import android.graphics.SweepGradient; import android.graphics.TemporaryBuffer; import android.text.GraphicsOperations; import android.text.SpannableString; Loading Loading @@ -593,7 +589,9 @@ class GLES20Canvas extends Canvas { if ((index | count | (index + count) | (text.length - index - count)) < 0) { throw new IndexOutOfBoundsException(); } boolean hasShader = setupShader(paint); nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); if (hasShader) nResetShader(mRenderer); } private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y, Loading @@ -601,6 +599,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); if (text instanceof String || text instanceof SpannedString || text instanceof SpannableString) { nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, Loading @@ -614,6 +613,7 @@ class GLES20Canvas extends Canvas { nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint); TemporaryBuffer.recycle(buf); } if (hasShader) nResetShader(mRenderer); } @Override Loading @@ -621,7 +621,9 @@ class GLES20Canvas extends Canvas { if ((start | end | (end - start) | (text.length() - end)) < 0) { throw new IndexOutOfBoundsException(); } boolean hasShader = setupShader(paint); nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); if (hasShader) nResetShader(mRenderer); } private native void nDrawText(int renderer, String text, int start, int end, float x, float y, Loading @@ -629,7 +631,9 @@ class GLES20Canvas extends Canvas { @Override public void drawText(String text, float x, float y, Paint paint) { boolean hasShader = setupShader(paint); nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint); if (hasShader) nResetShader(mRenderer); } @Override Loading Loading @@ -665,28 +669,12 @@ class GLES20Canvas extends Canvas { private boolean setupShader(Paint paint) { final Shader shader = paint.getShader(); if (shader != null) { if (shader instanceof BitmapShader) { final BitmapShader bs = (BitmapShader) shader; nSetupBitmapShader(mRenderer, bs.native_instance, bs.mBitmap.mNativeBitmap, bs.mTileX, bs.mTileY, bs.mLocalMatrix); return true; } else if (shader instanceof LinearGradient) { final LinearGradient ls = (LinearGradient) shader; nSetupLinearShader(mRenderer, ls.native_instance, ls.bounds, ls.colors, ls.positions, ls.count, ls.tileMode, ls.mLocalMatrix); nSetupShader(mRenderer, shader.native_shader); return true; } else if (shader instanceof RadialGradient) { // TODO: Implement } else if (shader instanceof SweepGradient) { // TODO: Implement } } return false; } private native void nSetupLinearShader(int renderer, int shader, int bounds, int colors, int positions, int count, int tileMode, int localMatrix); private native void nSetupBitmapShader(int renderer, int shader, int bitmap, int tileX, int tileY, int matrix); private native void nSetupShader(int renderer, int shader); private native void nResetShader(int renderer); } core/jni/android/graphics/Shader.cpp +116 −75 Original line number Diff line number Diff line Loading @@ -8,12 +8,14 @@ #include "SkTemplates.h" #include "SkXfermode.h" #include <SkiaShader.h> using namespace android::uirenderer; static struct { jclass clazz; jfieldID bounds; jfieldID colors; jfieldID positions; } gLinearGradientClassInfo; jfieldID shader; } gShaderClassInfo; static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { if (NULL == ptr) { Loading Loading @@ -48,8 +50,9 @@ static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArra /////////////////////////////////////////////////////////////////////////////////////////////// static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader) static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader) { delete skiaShader; shader->safeUnref(); } Loading @@ -58,7 +61,8 @@ static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, return shader ? shader->getLocalMatrix(matrix) : false; } static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix) static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader, const SkMatrix* matrix) { if (shader) { if (NULL == matrix) { Loading @@ -67,30 +71,33 @@ static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const else { shader->setLocalMatrix(*matrix); } skiaShader->setMatrix(const_cast<SkMatrix*>(matrix)); } } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* BitmapShader_constructor(JNIEnv* env, jobject, const SkBitmap* bitmap, static SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap, int tileModeX, int tileModeY) { SkShader* s = SkShader::CreateBitmapShader(*bitmap, (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); ThrowIAE_IfNull(env, s); return s; } /////////////////////////////////////////////////////////////////////////////////////////////// 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 SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader, SkBitmap* bitmap, int tileModeX, int tileModeY) { SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader, static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY), NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); return skiaShader; } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, float x0, float y0, float x1, float y1, jintArray colorArray, jfloatArray posArray, int tileMode) Loading @@ -105,19 +112,43 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); SkScalar* pos = NULL; if (posArray) { AutoJavaFloatArray autoPos(env, posArray, count); const float* posValues = autoPos.ptr(); pos = (SkScalar*)storage.get(); for (size_t i = 0; i < count; i++) { pos[i] = SkFloatToScalar(posValues[i]); } } SkShader* shader = SkGradientShader::CreateLinear(pts, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode)); env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; } static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, float x0, float y0, float x1, float y1, jintArray colorArray, jfloatArray posArray, int tileMode) { size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, 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]; uint32_t* storedColors = new uint32_t[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++) { pos[i] = SkFloatToScalar(posValues[i]); storedPositions[i] = posValues[i]; } } else { Loading @@ -125,32 +156,16 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, 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)); SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, storedPositions, count, shader, static_cast<SkShader::TileMode>(tileMode), NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); SkShader* shader = SkGradientShader::CreateLinear(pts, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode)); env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); return skiaShader; } static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { SkPoint pts[2]; pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; static SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { float* storedBounds = new float[4]; storedBounds[0] = x0; storedBounds[1] = y0; storedBounds[2] = x1; storedBounds[3] = y1; Loading @@ -163,11 +178,27 @@ static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, 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)); SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); return skiaShader; } static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { SkPoint pts[2]; pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); ThrowIAE_IfNull(env, s); return s; } Loading Loading @@ -268,18 +299,38 @@ static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* ComposeShader_create1(JNIEnv* env, jobject, static SkShader* ComposeShader_create1(JNIEnv* env, jobject o, SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) { return new SkComposeShader(shaderA, shaderB, mode); } static SkShader* ComposeShader_create2(JNIEnv* env, jobject, SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode mode) static SkShader* ComposeShader_create2(JNIEnv* env, jobject o, SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode) { SkAutoUnref au(SkPorterDuff::CreateXfermode(mode)); SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); SkXfermode* mode = (SkXfermode*) au.get(); return new SkComposeShader(shaderA, shaderB, mode); } return new SkComposeShader(shaderA, shaderB, (SkXfermode*)au.get()); static SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) { SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); SkXfermode* mode = (SkXfermode*) au.get(); SkXfermode::Mode skiaMode; if (!SkXfermode::IsMode(mode, &skiaMode)) { skiaMode = SkXfermode::kSrcOver_Mode; } return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); } static SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) { SkXfermode::Mode skiaMode; if (!SkXfermode::IsMode(mode, &skiaMode)) { skiaMode = SkXfermode::kSrcOver_Mode; } return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); } /////////////////////////////////////////////////////////////////////////////////////////////// Loading @@ -290,19 +341,21 @@ static JNINativeMethod gColorMethods[] = { }; static JNINativeMethod gShaderMethods[] = { { "nativeDestructor", "(I)V", (void*)Shader_destructor }, { "nativeDestructor", "(II)V", (void*)Shader_destructor }, { "nativeGetLocalMatrix", "(II)Z", (void*)Shader_getLocalMatrix }, { "nativeSetLocalMatrix", "(II)V", (void*)Shader_setLocalMatrix } { "nativeSetLocalMatrix", "(III)V", (void*)Shader_setLocalMatrix } }; static JNINativeMethod gBitmapShaderMethods[] = { { "nativeCreate", "(III)I", (void*)BitmapShader_constructor } { "nativeCreate", "(III)I", (void*)BitmapShader_constructor }, { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor } }; static JNINativeMethod gLinearGradientMethods[] = { { "nativeDestructor", "(I)V", (void*)LinearGradient_destructor }, { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 } { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }, { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 }, { "nativePostCreate2", "(IFFFFIII)I", (void*)LinearGradient_postCreate2 } }; static JNINativeMethod gRadialGradientMethods[] = { Loading @@ -317,7 +370,9 @@ static JNINativeMethod gSweepGradientMethods[] = { static JNINativeMethod gComposeShaderMethods[] = { {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 } {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, {"nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, {"nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } }; #include <android_runtime/AndroidRuntime.h> Loading @@ -326,15 +381,6 @@ static JNINativeMethod gComposeShaderMethods[] = { 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) { Loading @@ -348,11 +394,6 @@ 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; } core/jni/android_view_GLES20Canvas.cpp +5 −14 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <SkXfermode.h> #include <OpenGLRenderer.h> #include <SkiaShader.h> #include <Rect.h> #include <ui/Rect.h> Loading Loading @@ -235,18 +236,9 @@ static void android_view_GLES20Canvas_resetShader(JNIEnv* env, jobject canvas, renderer->resetShader(); } static void android_view_GLES20Canvas_setupBitmapShader(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, SkShader* shader, SkBitmap* bitmap, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix) { renderer->setupBitmapShader(bitmap, tileX, tileY, matrix, (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, int count, SkShader::TileMode tileMode, SkMatrix* matrix) { renderer->setupLinearGradientShader(shader, bounds, colors, positions, count, tileMode, matrix, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, SkiaShader* shader) { renderer->setupShader(shader); } // ---------------------------------------------------------------------------- Loading Loading @@ -320,8 +312,7 @@ static JNINativeMethod gMethods[] = { { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, { "nResetShader", "(I)V", (void*) android_view_GLES20Canvas_resetShader }, { "nSetupBitmapShader", "(IIIIII)V", (void*) android_view_GLES20Canvas_setupBitmapShader }, { "nSetupLinearShader", "(IIIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader }, { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader }, { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray }, { "nDrawText", "(ILjava/lang/String;IIFFII)V", Loading graphics/java/android/graphics/BitmapShader.java +6 −20 Original line number Diff line number Diff line Loading @@ -21,21 +21,6 @@ package android.graphics; * mirrored by setting the tiling mode. */ public class BitmapShader extends Shader { /** * We hold on just for the GC, since our native counterpart is using it. * * @hide */ public Bitmap mBitmap; /** * @hide */ public int mTileX; /** * @hide */ public int mTileY; /** * Call this to create a new shader that will draw with a bitmap. * Loading @@ -44,12 +29,13 @@ public class BitmapShader extends Shader { * @param tileY The tiling mode for y to draw the bitmap in. */ public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) { mBitmap = bitmap; mTileX = tileX.nativeInt; mTileY = tileY.nativeInt; native_instance = nativeCreate(bitmap.ni(), mTileX, mTileY); final int b = bitmap.ni(); native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt); native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt); } private static native int nativeCreate(int native_bitmap, int shaderTileModeX, int shaderTileModeY); private static native int nativePostCreate(int native_shader, int native_bitmap, int shaderTileModeX, int shaderTileModeY); } graphics/java/android/graphics/ComposeShader.java +14 −5 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ public class ComposeShader extends Shader { public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) { native_instance = nativeCreate1(shaderA.native_instance, shaderB.native_instance, (mode != null) ? mode.native_instance : 0); native_shader = nativePostCreate1(native_instance, shaderA.native_shader, shaderB.native_shader, (mode != null) ? mode.native_instance : 0); } /** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode. Loading @@ -43,9 +45,16 @@ public class ComposeShader extends Shader { public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) { native_instance = nativeCreate2(shaderA.native_instance, shaderB.native_instance, mode.nativeInt); native_shader = nativePostCreate2(native_instance, shaderA.native_shader, shaderB.native_shader, mode.nativeInt); } private static native int nativeCreate1(int native_shaderA, int native_shaderB, int native_mode); private static native int nativeCreate2(int native_shaderA, int native_shaderB, int porterDuffMode); private static native int nativeCreate1(int native_shaderA, int native_shaderB, int native_mode); private static native int nativeCreate2(int native_shaderA, int native_shaderB, int porterDuffMode); private static native int nativePostCreate1(int native_shader, int native_skiaShaderA, int native_skiaShaderB, int native_mode); private static native int nativePostCreate2(int native_shader, int native_skiaShaderA, int native_skiaShaderB, int porterDuffMode); } Loading
core/java/android/view/GLES20Canvas.java +11 −23 Original line number Diff line number Diff line Loading @@ -17,21 +17,17 @@ package android.view; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.DrawFilter; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Picture; import android.graphics.PorterDuff; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; import android.graphics.SweepGradient; import android.graphics.TemporaryBuffer; import android.text.GraphicsOperations; import android.text.SpannableString; Loading Loading @@ -593,7 +589,9 @@ class GLES20Canvas extends Canvas { if ((index | count | (index + count) | (text.length - index - count)) < 0) { throw new IndexOutOfBoundsException(); } boolean hasShader = setupShader(paint); nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); if (hasShader) nResetShader(mRenderer); } private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y, Loading @@ -601,6 +599,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); if (text instanceof String || text instanceof SpannedString || text instanceof SpannableString) { nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, Loading @@ -614,6 +613,7 @@ class GLES20Canvas extends Canvas { nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint); TemporaryBuffer.recycle(buf); } if (hasShader) nResetShader(mRenderer); } @Override Loading @@ -621,7 +621,9 @@ class GLES20Canvas extends Canvas { if ((start | end | (end - start) | (text.length() - end)) < 0) { throw new IndexOutOfBoundsException(); } boolean hasShader = setupShader(paint); nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); if (hasShader) nResetShader(mRenderer); } private native void nDrawText(int renderer, String text, int start, int end, float x, float y, Loading @@ -629,7 +631,9 @@ class GLES20Canvas extends Canvas { @Override public void drawText(String text, float x, float y, Paint paint) { boolean hasShader = setupShader(paint); nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint); if (hasShader) nResetShader(mRenderer); } @Override Loading Loading @@ -665,28 +669,12 @@ class GLES20Canvas extends Canvas { private boolean setupShader(Paint paint) { final Shader shader = paint.getShader(); if (shader != null) { if (shader instanceof BitmapShader) { final BitmapShader bs = (BitmapShader) shader; nSetupBitmapShader(mRenderer, bs.native_instance, bs.mBitmap.mNativeBitmap, bs.mTileX, bs.mTileY, bs.mLocalMatrix); return true; } else if (shader instanceof LinearGradient) { final LinearGradient ls = (LinearGradient) shader; nSetupLinearShader(mRenderer, ls.native_instance, ls.bounds, ls.colors, ls.positions, ls.count, ls.tileMode, ls.mLocalMatrix); nSetupShader(mRenderer, shader.native_shader); return true; } else if (shader instanceof RadialGradient) { // TODO: Implement } else if (shader instanceof SweepGradient) { // TODO: Implement } } return false; } private native void nSetupLinearShader(int renderer, int shader, int bounds, int colors, int positions, int count, int tileMode, int localMatrix); private native void nSetupBitmapShader(int renderer, int shader, int bitmap, int tileX, int tileY, int matrix); private native void nSetupShader(int renderer, int shader); private native void nResetShader(int renderer); }
core/jni/android/graphics/Shader.cpp +116 −75 Original line number Diff line number Diff line Loading @@ -8,12 +8,14 @@ #include "SkTemplates.h" #include "SkXfermode.h" #include <SkiaShader.h> using namespace android::uirenderer; static struct { jclass clazz; jfieldID bounds; jfieldID colors; jfieldID positions; } gLinearGradientClassInfo; jfieldID shader; } gShaderClassInfo; static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { if (NULL == ptr) { Loading Loading @@ -48,8 +50,9 @@ static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArra /////////////////////////////////////////////////////////////////////////////////////////////// static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader) static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader) { delete skiaShader; shader->safeUnref(); } Loading @@ -58,7 +61,8 @@ static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, return shader ? shader->getLocalMatrix(matrix) : false; } static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix) static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader, const SkMatrix* matrix) { if (shader) { if (NULL == matrix) { Loading @@ -67,30 +71,33 @@ static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const else { shader->setLocalMatrix(*matrix); } skiaShader->setMatrix(const_cast<SkMatrix*>(matrix)); } } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* BitmapShader_constructor(JNIEnv* env, jobject, const SkBitmap* bitmap, static SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap, int tileModeX, int tileModeY) { SkShader* s = SkShader::CreateBitmapShader(*bitmap, (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); ThrowIAE_IfNull(env, s); return s; } /////////////////////////////////////////////////////////////////////////////////////////////// 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 SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader, SkBitmap* bitmap, int tileModeX, int tileModeY) { SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader, static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY), NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); return skiaShader; } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, float x0, float y0, float x1, float y1, jintArray colorArray, jfloatArray posArray, int tileMode) Loading @@ -105,19 +112,43 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); SkScalar* pos = NULL; if (posArray) { AutoJavaFloatArray autoPos(env, posArray, count); const float* posValues = autoPos.ptr(); pos = (SkScalar*)storage.get(); for (size_t i = 0; i < count; i++) { pos[i] = SkFloatToScalar(posValues[i]); } } SkShader* shader = SkGradientShader::CreateLinear(pts, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode)); env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; } static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, float x0, float y0, float x1, float y1, jintArray colorArray, jfloatArray posArray, int tileMode) { size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, 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]; uint32_t* storedColors = new uint32_t[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++) { pos[i] = SkFloatToScalar(posValues[i]); storedPositions[i] = posValues[i]; } } else { Loading @@ -125,32 +156,16 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, 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)); SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, storedPositions, count, shader, static_cast<SkShader::TileMode>(tileMode), NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); SkShader* shader = SkGradientShader::CreateLinear(pts, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode)); env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); return skiaShader; } static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { SkPoint pts[2]; pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; static SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { float* storedBounds = new float[4]; storedBounds[0] = x0; storedBounds[1] = y0; storedBounds[2] = x1; storedBounds[3] = y1; Loading @@ -163,11 +178,27 @@ static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, 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)); SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); return skiaShader; } static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { SkPoint pts[2]; pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); ThrowIAE_IfNull(env, s); return s; } Loading Loading @@ -268,18 +299,38 @@ static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* ComposeShader_create1(JNIEnv* env, jobject, static SkShader* ComposeShader_create1(JNIEnv* env, jobject o, SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) { return new SkComposeShader(shaderA, shaderB, mode); } static SkShader* ComposeShader_create2(JNIEnv* env, jobject, SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode mode) static SkShader* ComposeShader_create2(JNIEnv* env, jobject o, SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode) { SkAutoUnref au(SkPorterDuff::CreateXfermode(mode)); SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); SkXfermode* mode = (SkXfermode*) au.get(); return new SkComposeShader(shaderA, shaderB, mode); } return new SkComposeShader(shaderA, shaderB, (SkXfermode*)au.get()); static SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) { SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); SkXfermode* mode = (SkXfermode*) au.get(); SkXfermode::Mode skiaMode; if (!SkXfermode::IsMode(mode, &skiaMode)) { skiaMode = SkXfermode::kSrcOver_Mode; } return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); } static SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) { SkXfermode::Mode skiaMode; if (!SkXfermode::IsMode(mode, &skiaMode)) { skiaMode = SkXfermode::kSrcOver_Mode; } return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); } /////////////////////////////////////////////////////////////////////////////////////////////// Loading @@ -290,19 +341,21 @@ static JNINativeMethod gColorMethods[] = { }; static JNINativeMethod gShaderMethods[] = { { "nativeDestructor", "(I)V", (void*)Shader_destructor }, { "nativeDestructor", "(II)V", (void*)Shader_destructor }, { "nativeGetLocalMatrix", "(II)Z", (void*)Shader_getLocalMatrix }, { "nativeSetLocalMatrix", "(II)V", (void*)Shader_setLocalMatrix } { "nativeSetLocalMatrix", "(III)V", (void*)Shader_setLocalMatrix } }; static JNINativeMethod gBitmapShaderMethods[] = { { "nativeCreate", "(III)I", (void*)BitmapShader_constructor } { "nativeCreate", "(III)I", (void*)BitmapShader_constructor }, { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor } }; static JNINativeMethod gLinearGradientMethods[] = { { "nativeDestructor", "(I)V", (void*)LinearGradient_destructor }, { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 } { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }, { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 }, { "nativePostCreate2", "(IFFFFIII)I", (void*)LinearGradient_postCreate2 } }; static JNINativeMethod gRadialGradientMethods[] = { Loading @@ -317,7 +370,9 @@ static JNINativeMethod gSweepGradientMethods[] = { static JNINativeMethod gComposeShaderMethods[] = { {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 } {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, {"nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, {"nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } }; #include <android_runtime/AndroidRuntime.h> Loading @@ -326,15 +381,6 @@ static JNINativeMethod gComposeShaderMethods[] = { 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) { Loading @@ -348,11 +394,6 @@ 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; }
core/jni/android_view_GLES20Canvas.cpp +5 −14 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <SkXfermode.h> #include <OpenGLRenderer.h> #include <SkiaShader.h> #include <Rect.h> #include <ui/Rect.h> Loading Loading @@ -235,18 +236,9 @@ static void android_view_GLES20Canvas_resetShader(JNIEnv* env, jobject canvas, renderer->resetShader(); } static void android_view_GLES20Canvas_setupBitmapShader(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, SkShader* shader, SkBitmap* bitmap, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix) { renderer->setupBitmapShader(bitmap, tileX, tileY, matrix, (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, int count, SkShader::TileMode tileMode, SkMatrix* matrix) { renderer->setupLinearGradientShader(shader, bounds, colors, positions, count, tileMode, matrix, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, SkiaShader* shader) { renderer->setupShader(shader); } // ---------------------------------------------------------------------------- Loading Loading @@ -320,8 +312,7 @@ static JNINativeMethod gMethods[] = { { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, { "nResetShader", "(I)V", (void*) android_view_GLES20Canvas_resetShader }, { "nSetupBitmapShader", "(IIIIII)V", (void*) android_view_GLES20Canvas_setupBitmapShader }, { "nSetupLinearShader", "(IIIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader }, { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader }, { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray }, { "nDrawText", "(ILjava/lang/String;IIFFII)V", Loading
graphics/java/android/graphics/BitmapShader.java +6 −20 Original line number Diff line number Diff line Loading @@ -21,21 +21,6 @@ package android.graphics; * mirrored by setting the tiling mode. */ public class BitmapShader extends Shader { /** * We hold on just for the GC, since our native counterpart is using it. * * @hide */ public Bitmap mBitmap; /** * @hide */ public int mTileX; /** * @hide */ public int mTileY; /** * Call this to create a new shader that will draw with a bitmap. * Loading @@ -44,12 +29,13 @@ public class BitmapShader extends Shader { * @param tileY The tiling mode for y to draw the bitmap in. */ public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) { mBitmap = bitmap; mTileX = tileX.nativeInt; mTileY = tileY.nativeInt; native_instance = nativeCreate(bitmap.ni(), mTileX, mTileY); final int b = bitmap.ni(); native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt); native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt); } private static native int nativeCreate(int native_bitmap, int shaderTileModeX, int shaderTileModeY); private static native int nativePostCreate(int native_shader, int native_bitmap, int shaderTileModeX, int shaderTileModeY); }
graphics/java/android/graphics/ComposeShader.java +14 −5 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ public class ComposeShader extends Shader { public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) { native_instance = nativeCreate1(shaderA.native_instance, shaderB.native_instance, (mode != null) ? mode.native_instance : 0); native_shader = nativePostCreate1(native_instance, shaderA.native_shader, shaderB.native_shader, (mode != null) ? mode.native_instance : 0); } /** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode. Loading @@ -43,9 +45,16 @@ public class ComposeShader extends Shader { public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) { native_instance = nativeCreate2(shaderA.native_instance, shaderB.native_instance, mode.nativeInt); native_shader = nativePostCreate2(native_instance, shaderA.native_shader, shaderB.native_shader, mode.nativeInt); } private static native int nativeCreate1(int native_shaderA, int native_shaderB, int native_mode); private static native int nativeCreate2(int native_shaderA, int native_shaderB, int porterDuffMode); private static native int nativeCreate1(int native_shaderA, int native_shaderB, int native_mode); private static native int nativeCreate2(int native_shaderA, int native_shaderB, int porterDuffMode); private static native int nativePostCreate1(int native_shader, int native_skiaShaderA, int native_skiaShaderB, int native_mode); private static native int nativePostCreate2(int native_shader, int native_skiaShaderA, int native_skiaShaderB, int porterDuffMode); }