diff options
-rw-r--r-- | core/jni/android/graphics/Shader.cpp | 59 | ||||
-rw-r--r-- | graphics/java/android/graphics/Shader.java | 3 | ||||
-rw-r--r-- | graphics/java/android/graphics/SweepGradient.java | 13 | ||||
-rw-r--r-- | libs/hwui/GradientCache.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/GradientCache.h | 4 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 67 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.h | 30 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 62 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.h | 20 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 11 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java | 96 |
11 files changed, 329 insertions, 38 deletions
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index 92024296eb31..344669c40da8 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -318,6 +318,59 @@ static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, return s; } +static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, + float x, float y, jintArray colorArray, jfloatArray posArray) { +#ifdef USE_OPENGL_RENDERER + size_t count = env->GetArrayLength(colorArray); + const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); + + jfloat* storedPositions = new jfloat[count]; + uint32_t* storedColors = new uint32_t[count]; + for (size_t i = 0; i < count; i++) { + storedColors[i] = static_cast<uint32_t>(colorValues[i]); + } + + if (posArray) { + AutoJavaFloatArray autoPos(env, posArray, count); + const float* posValues = autoPos.ptr(); + for (size_t i = 0; i < count; i++) { + storedPositions[i] = posValues[i]; + } + } else { + storedPositions[0] = 0.0f; + storedPositions[1] = 1.0f; + } + + SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count, + shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); + + env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); + return skiaShader; +#else + return NULL; +#endif +} + +static SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, + float x, float y, int color0, int color1) { +#ifdef USE_OPENGL_RENDERER + float* storedPositions = new float[2]; + storedPositions[0] = 0.0f; + storedPositions[1] = 1.0f; + + uint32_t* storedColors = new uint32_t[2]; + storedColors[0] = static_cast<uint32_t>(color0); + storedColors[1] = static_cast<uint32_t>(color1); + + SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2, + shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); + + return skiaShader; +#else + return NULL; +#endif +} + /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* ComposeShader_create1(JNIEnv* env, jobject o, @@ -389,8 +442,10 @@ static JNINativeMethod gRadialGradientMethods[] = { }; static JNINativeMethod gSweepGradientMethods[] = { - {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, - {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 } + {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, + {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }, + { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 }, + { "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 } }; static JNINativeMethod gComposeShaderMethods[] = { diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java index b397662b391d..0400b5c9e4aa 100644 --- a/graphics/java/android/graphics/Shader.java +++ b/graphics/java/android/graphics/Shader.java @@ -71,7 +71,8 @@ public class Shader { * @param localM The shader's new local matrix, or null to specify identity */ public void setLocalMatrix(Matrix localM) { - nativeSetLocalMatrix(native_instance, native_shader, localM.native_instance); + nativeSetLocalMatrix(native_instance, native_shader, + localM == null ? 0 : localM.native_instance); } protected void finalize() throws Throwable { diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java index 7456993d4017..2afdd4dd5835 100644 --- a/graphics/java/android/graphics/SweepGradient.java +++ b/graphics/java/android/graphics/SweepGradient.java @@ -42,6 +42,7 @@ public class SweepGradient extends Shader { "color and position arrays must be of equal length"); } native_instance = nativeCreate1(cx, cy, colors, positions); + native_shader = nativePostCreate1(native_instance, cx, cy, colors, positions); } /** @@ -54,11 +55,15 @@ public class SweepGradient extends Shader { */ public SweepGradient(float cx, float cy, int color0, int color1) { native_instance = nativeCreate2(cx, cy, color0, color1); + native_shader = nativePostCreate2(native_instance, cx, cy, color0, color1); } - private static native int nativeCreate1(float x, float y, - int colors[], float positions[]); - private static native int nativeCreate2(float x, float y, - int color0, int color1); + private static native int nativeCreate1(float x, float y, int colors[], float positions[]); + private static native int nativeCreate2(float x, float y, int color0, int color1); + + private static native int nativePostCreate1(int native_shader, float cx, float cy, + int[] colors, float[] positions); + private static native int nativePostCreate2(int native_shader, float cx, float cy, + int color0, int color1); } diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 9957370a5ae6..97f4cb468c53 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -116,7 +116,7 @@ void GradientCache::clear() { mCache.clear(); } -Texture* GradientCache::addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, +Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1); diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index 51a8c0185adb..c829fd468007 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -46,8 +46,8 @@ public: * Adds a new linear gradient to the cache. The generated texture is * returned. */ - Texture* addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, - float* positions, int count, SkShader::TileMode tileMode); + Texture* addLinearGradient(SkShader* shader, uint32_t* colors, float* positions, + int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode); /** * Returns the texture associated with the specified shader. */ diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index becbc2277866..bcc1edfbb13c 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -33,11 +33,18 @@ const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n"; const char* gVS_Header_Uniforms = "uniform mat4 transform;\n"; -const char* gVS_Header_Uniforms_HasGradient = +const char* gVS_Header_Uniforms_HasGradient[3] = { + // Linear "uniform float gradientLength;\n" "uniform vec2 gradient;\n" "uniform vec2 gradientStart;\n" - "uniform mat4 screenSpace;\n"; + "uniform mat4 screenSpace;\n", + // Circular + "", + // Sweep + "uniform vec2 gradientStart;\n" + "uniform mat4 screenSpace;\n" +}; const char* gVS_Header_Uniforms_HasBitmap = "uniform mat4 textureTransform;\n" "uniform vec2 textureDimension;\n"; @@ -45,15 +52,28 @@ const char* gVS_Header_Varyings_HasTexture = "varying vec2 outTexCoords;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying vec2 outBitmapTexCoords;\n"; -const char* gVS_Header_Varyings_HasGradient = - "varying float index;\n"; +const char* gVS_Header_Varyings_HasGradient[3] = { + // Linear + "varying float index;\n", + // Circular + "", + // Sweep + "varying vec2 sweep;\n" +}; const char* gVS_Main = "\nvoid main(void) {\n"; const char* gVS_Main_OutTexCoords = " outTexCoords = texCoords;\n"; -const char* gVS_Main_OutGradientIndex = +const char* gVS_Main_OutGradient[3] = { + // Linear " vec4 location = screenSpace * position;\n" - " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n"; + " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n", + // Circular + "", + // Sweep + " vec4 location = screenSpace * position;\n" + " sweep = location.xy - gradientStart;\n" +}; const char* gVS_Main_OutBitmapTexCoords = " vec4 bitmapCoords = textureTransform * position;\n" " outBitmapTexCoords = bitmapCoords.xy * textureDimension;\n"; @@ -74,8 +94,14 @@ const char* gFS_Uniforms_Color = "uniform vec4 color;\n"; const char* gFS_Uniforms_TextureSampler = "uniform sampler2D sampler;\n"; -const char* gFS_Uniforms_GradientSampler = - "uniform sampler2D gradientSampler;\n"; +const char* gFS_Uniforms_GradientSampler[3] = { + // Linear + "uniform sampler2D gradientSampler;\n", + // Circular + "uniform sampler2D gradientSampler;\n", + // Sweep + "uniform sampler2D gradientSampler;\n" +}; const char* gFS_Uniforms_BitmapSampler = "uniform sampler2D bitmapSampler;\n"; const char* gFS_Uniforms_ColorOp[4] = { @@ -99,8 +125,15 @@ const char* gFS_Main_FetchTexture = " fragColor = color * texture2D(sampler, outTexCoords);\n"; const char* gFS_Main_FetchA8Texture = " fragColor = color * texture2D(sampler, outTexCoords).a;\n"; -const char* gFS_Main_FetchGradient = - " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n"; +const char* gFS_Main_FetchGradient[3] = { + // Linear + " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", + // Circular + "", + // Sweep + " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" + " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n" +}; const char* gFS_Main_FetchBitmap = " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; const char* gFS_Main_FetchBitmapNpot = @@ -217,7 +250,7 @@ Program* ProgramCache::get(const ProgramDescription& description) { ssize_t index = mCache.indexOfKey(key); Program* program = NULL; if (index < 0) { - PROGRAM_LOGD("Could not find program with key 0x%x", key); + description.log("Could not find program"); program = generateProgram(description, key); mCache.add(key, program); } else { @@ -247,7 +280,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description // Uniforms shader.append(gVS_Header_Uniforms); if (description.hasGradient) { - shader.append(gVS_Header_Uniforms_HasGradient); + shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Header_Uniforms_HasBitmap); @@ -257,7 +290,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasGradient) { - shader.append(gVS_Header_Varyings_HasGradient); + shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Header_Varyings_HasBitmap); @@ -269,7 +302,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Main_OutTexCoords); } if (description.hasGradient) { - shader.append(gVS_Main_OutGradientIndex); + shader.append(gVS_Main_OutGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Main_OutBitmapTexCoords); @@ -301,7 +334,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasGradient) { - shader.append(gVS_Header_Varyings_HasGradient); + shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Header_Varyings_HasBitmap); @@ -314,7 +347,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Uniforms_TextureSampler); } if (description.hasGradient) { - shader.append(gFS_Uniforms_GradientSampler); + shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); } if (description.hasBitmap) { shader.append(gFS_Uniforms_BitmapSampler); @@ -348,7 +381,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_FetchColor); } if (description.hasGradient) { - shader.append(gFS_Main_FetchGradient); + shader.append(gFS_Main_FetchGradient[description.gradientType]); } if (description.hasBitmap) { if (!description.isBitmapNpot) { diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index 0a1705279e7f..4fa80111d358 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -44,9 +44,6 @@ namespace uirenderer { #define PROGRAM_LOGD(...) #endif -/* - * IMPORTANT: All 32 bits are used, switch to a long. - */ #define PROGRAM_KEY_TEXTURE 0x1 #define PROGRAM_KEY_A8_TEXTURE 0x2 #define PROGRAM_KEY_BITMAP 0x4 @@ -70,14 +67,13 @@ namespace uirenderer { #define PROGRAM_BITMAP_WRAPS_SHIFT 9 #define PROGRAM_BITMAP_WRAPT_SHIFT 11 +#define PROGRAM_GRADIENT_TYPE_SHIFT 33 + /////////////////////////////////////////////////////////////////////////////// // Types /////////////////////////////////////////////////////////////////////////////// -/* - * IMPORTANT: All 32 bits are used, switch to a long. - */ -typedef uint32_t programid; +typedef uint64_t programid; /////////////////////////////////////////////////////////////////////////////// // Cache @@ -96,9 +92,16 @@ struct ProgramDescription { kColorBlend }; + enum Gradient { + kGradientLinear, + kGradientCircular, + kGradientSweep + }; + ProgramDescription(): hasTexture(false), hasAlpha8Texture(false), hasBitmap(false), isBitmapNpot(false), hasGradient(false), + gradientType(kGradientLinear), shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false), bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE), colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode), @@ -112,8 +115,12 @@ struct ProgramDescription { // Shaders bool hasBitmap; bool isBitmapNpot; + bool hasGradient; + Gradient gradientType; + SkXfermode::Mode shadersMode; + bool isBitmapFirst; GLenum bitmapWrapS; GLenum bitmapWrapT; @@ -152,7 +159,8 @@ struct ProgramDescription { } } if (hasGradient) key |= PROGRAM_KEY_GRADIENT; - if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST; + key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT; + if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST; if (hasBitmap && hasGradient) { key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT; } @@ -174,6 +182,12 @@ struct ProgramDescription { if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST; return key; } + + void log(const char* message) const { + programid k = key(); + PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), + uint32_t(k & 0xffffffff)); + } }; // struct ProgramDescription /** diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 946cc4b95c94..c5d97674ad7a 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -164,6 +164,7 @@ SkiaLinearGradientShader::~SkiaLinearGradientShader() { void SkiaLinearGradientShader::describe(ProgramDescription& description, const Extensions& extensions) { description.hasGradient = true; + description.gradientType = ProgramDescription::kGradientLinear; } void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView, @@ -173,8 +174,7 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV Texture* texture = mGradientCache->get(mKey); if (!texture) { - texture = mGradientCache->addLinearGradient(mKey, mBounds, mColors, mPositions, - mCount, mTileX); + texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX); } Rect start(mBounds[0], mBounds[1], mBounds[2], mBounds[3]); @@ -209,6 +209,64 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo } /////////////////////////////////////////////////////////////////////////////// +// Sweep gradient shader +/////////////////////////////////////////////////////////////////////////////// + +SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors, + float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend): + SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode, matrix, blend), + mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { +} + +SkiaSweepGradientShader::~SkiaSweepGradientShader() { + delete[] mColors; + delete[] mPositions; +} + +void SkiaSweepGradientShader::describe(ProgramDescription& description, + const Extensions& extensions) { + description.hasGradient = true; + description.gradientType = ProgramDescription::kGradientSweep; +} + +void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView, + const Snapshot& snapshot, GLuint* textureUnit) { + GLuint textureSlot = (*textureUnit)++; + glActiveTexture(gTextureUnitsMap[textureSlot]); + + Texture* texture = mGradientCache->get(mKey); + if (!texture) { + texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount); + } + + float left = mX; + float top = mY; + + if (mMatrix) { + mat4 shaderMatrix(*mMatrix); + shaderMatrix.mapPoint(left, top); + } + snapshot.transform->mapPoint(left, top); + + mat4 screenSpace(*snapshot.transform); + screenSpace.multiply(modelView); + + // Uniforms + bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot); + glUniform1i(program->getUniform("gradientSampler"), textureSlot); + glUniform2f(program->getUniform("gradientStart"), left, top); + glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); +} + +void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView, + const Snapshot& snapshot) { + mat4 screenSpace(*snapshot.transform); + screenSpace.multiply(modelView); + glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); +} + +/////////////////////////////////////////////////////////////////////////////// // Compose shader /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index cc94ae6c815f..b67bfee66919 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -145,6 +145,26 @@ private: }; // struct SkiaLinearGradientShader /** + * A shader that draws a sweep gradient. + */ +struct SkiaSweepGradientShader: public SkiaShader { + SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count, + SkShader* key, SkMatrix* matrix, bool blend); + ~SkiaSweepGradientShader(); + + void describe(ProgramDescription& description, const Extensions& extensions); + void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, + GLuint* textureUnit); + void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); + +private: + float mX, mY; + uint32_t* mColors; + float* mPositions; + int mCount; +}; // struct SkiaSweepGradientShader + +/** * A shader that draws two shaders, composited with an xfermode. */ struct SkiaComposeShader: public SkiaShader { diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 8a08c48c0a11..af71a0f382b0 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -31,6 +31,15 @@ </activity> <activity + android:name="AdvancedGradientsActivity" + android:label="_Advanced Gradients"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="ResizeActivity" android:label="_Resize" android:windowSoftInputMode="adjustResize"> @@ -250,7 +259,7 @@ <activity android:name="AdvancedBlendActivity" - android:label="_AdvancedBlend"> + android:label="_Advanced Blend"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java new file mode 100644 index 000000000000..e2320216dd37 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java @@ -0,0 +1,96 @@ +/* + * 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.android.test.hwui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RadialGradient; +import android.graphics.Shader; +import android.graphics.SweepGradient; +import android.os.Bundle; +import android.view.View; + +@SuppressWarnings({"UnusedDeclaration"}) +public class AdvancedGradientsActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(new GradientsView(this)); + } + + static class GradientsView extends View { + private final Paint mPaint; + private final SweepGradient mSweepGradient; + private final RadialGradient mRadialGradient; + private final Matrix mMatrix; + private final Matrix mMatrix2; + + GradientsView(Context c) { + super(c); + + mSweepGradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff); + mRadialGradient = new RadialGradient(100.0f, 100.0f, 100.0f, 0xff000000, 0xffffffff, + Shader.TileMode.MIRROR); + + mMatrix = new Matrix(); + mMatrix.setTranslate(50.0f, 50.0f); + + mMatrix2 = new Matrix(); + mMatrix2.setScale(2.0f, 2.0f); + + mPaint = new Paint(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawRGB(255, 255, 255); + + // Bitmap shaders + canvas.save(); + canvas.translate(130.0f, 100.0f); + + mSweepGradient.setLocalMatrix(null); + mPaint.setShader(mSweepGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); + + canvas.translate(400.0f, 000.0f); + + mPaint.setShader(mRadialGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); + + canvas.translate(400.0f, 000.0f); + + mSweepGradient.setLocalMatrix(mMatrix); + mPaint.setShader(mSweepGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); + + canvas.translate(-800.0f, 300.0f); + + mSweepGradient.setLocalMatrix(mMatrix2); + mPaint.setShader(mSweepGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); + + + canvas.restore(); + } + } +} |