diff options
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 20 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 67 | ||||
-rw-r--r-- | libs/hwui/Matrix.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/Matrix.h | 3 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 161 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 38 | ||||
-rw-r--r-- | libs/hwui/shaders/drawColor.frag | 4 | ||||
-rw-r--r-- | libs/hwui/shaders/drawTexture.frag | 12 | ||||
-rw-r--r-- | libs/hwui/shaders/drawTexture.vert | 20 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java | 52 |
10 files changed, 332 insertions, 53 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 5c24058f9770..aafd3ffeb585 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -278,30 +278,34 @@ class GLES20Canvas extends Canvas { @Override public int saveLayer(RectF bounds, Paint paint, int saveFlags) { - // TODO: Implement - return 0; + return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags); } @Override public int saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags) { - // TODO: Implement - return 0; + int nativePaint = paint == null ? 0 : paint.mNativePaint; + return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); } + private native int nSaveLayer(int renderer, float left, float top, float right, float bottom, + int paint, int saveFlags); + @Override public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { - // TODO: Implement - return 0; + return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, + alpha, saveFlags); } @Override public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags) { - // TODO: Implement - return 0; + return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags); } + private native int nSaveLayerAlpha(int renderer, float left, float top, float right, + float bottom, int alpha, int saveFlags); + @Override public void restore() { nRestore(mRenderer); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index d3b65582778c..fd9ce445f5e4 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -92,6 +92,22 @@ static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canv } // ---------------------------------------------------------------------------- +// Layers +// ---------------------------------------------------------------------------- + +static jint android_view_GLES20Renderer_saveLayer(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, + SkPaint* paint, jint saveFlags) { + return renderer->saveLayer(left, top, right, bottom, paint, saveFlags); +} + +static jint android_view_GLES20Renderer_saveLayerAlpha(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, + jint alpha, jint saveFlags) { + return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); +} + +// ---------------------------------------------------------------------------- // Clipping // ---------------------------------------------------------------------------- @@ -178,30 +194,33 @@ static void android_view_GLES20Renderer_drawRect(JNIEnv* env, jobject canvas, const char* const kClassPathName = "android/view/GLES20Canvas"; static JNINativeMethod gMethods[] = { - { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer }, - { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer }, - { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport }, - { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare }, - - { "nSave", "(II)I", (void*) android_view_GLES20Renderer_save }, - { "nRestore", "(I)V", (void*) android_view_GLES20Renderer_restore }, - { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Renderer_restoreToCount }, - { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Renderer_getSaveCount }, - - { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Renderer_quickReject }, - { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF }, - { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect }, - - { "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate }, - { "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate }, - { "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale }, - - { "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix }, - { "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix }, - { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix }, - - { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor }, - { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Renderer_drawRect }, + { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer }, + { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer }, + { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport }, + { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare }, + + { "nSave", "(II)I", (void*) android_view_GLES20Renderer_save }, + { "nRestore", "(I)V", (void*) android_view_GLES20Renderer_restore }, + { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Renderer_restoreToCount }, + { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Renderer_getSaveCount }, + + { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Renderer_saveLayer }, + { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Renderer_saveLayerAlpha }, + + { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Renderer_quickReject }, + { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF }, + { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect }, + + { "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate }, + { "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate }, + { "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale }, + + { "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix }, + { "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix }, + { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix }, + + { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor }, + { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Renderer_drawRect }, { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Renderer_getClipBounds }, diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index c772f003f014..e9c7791677c9 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -97,6 +97,14 @@ void Matrix4::copyTo(float* v) const { memcpy(v, data, sizeof(data)); } +float Matrix4::getTranslateX() { + return data[12]; +} + +float Matrix4::getTranslateY() { + return data[13]; +} + void Matrix4::loadTranslate(float x, float y, float z) { loadIdentity(); data[12] = x; diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index fa9638bd1c83..40c80fa5313a 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -90,6 +90,9 @@ public: void mapRect(Rect& r) const; + float getTranslateX(); + float getTranslateY(); + void dump() const; private: diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 830e0c36ff83..786b927d35eb 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -27,6 +27,7 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#include <SkCanvas.h> #include <SkPaint.h> #include <SkXfermode.h> @@ -40,21 +41,31 @@ namespace uirenderer { // Defines /////////////////////////////////////////////////////////////////////////////// -#define V(x, y) { { x, y } } +#define SV(x, y) { { x, y } } +#define FV(x, y, u, v) { { x, y }, { u, v } } /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// const SimpleVertex gDrawColorVertices[] = { - V(0.0f, 0.0f), - V(1.0f, 0.0f), - V(0.0f, 1.0f), - V(1.0f, 1.0f) + SV(0.0f, 0.0f), + SV(1.0f, 0.0f), + SV(0.0f, 1.0f), + SV(1.0f, 1.0f) }; const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); const GLsizei gDrawColorVertexCount = 4; +const TextureVertex gDrawTextureVertices[] = { + FV(0.0f, 0.0f, 0.0f, 1.0f), + FV(1.0f, 0.0f, 1.0f, 1.0f), + FV(0.0f, 1.0f, 0.0f, 0.0f), + FV(1.0f, 1.0f, 1.0f, 0.0f) +}; +const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex); +const GLsizei gDrawTextureVertexCount = 4; + /////////////////////////////////////////////////////////////////////////////// // Shaders /////////////////////////////////////////////////////////////////////////////// @@ -64,6 +75,9 @@ const GLsizei gDrawColorVertexCount = 4; #include "shaders/drawColor.vert" #include "shaders/drawColor.frag" +#include "shaders/drawTexture.vert" +#include "shaders/drawTexture.frag" + Program::Program(const char* vertex, const char* fragment) { vertexShader = buildShader(vertex, GL_VERTEX_SHADER); fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); @@ -139,6 +153,15 @@ GLuint Program::buildShader(const char* source, GLenum type) { DrawColorProgram::DrawColorProgram(): Program(gDrawColorVertexShader, gDrawColorFragmentShader) { + getAttribsAndUniforms(); +} + +DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment): + Program(vertex, fragment) { + getAttribsAndUniforms(); +} + +void DrawColorProgram::getAttribsAndUniforms() { position = addAttrib("position"); color = addAttrib("color"); projection = addUniform("projection"); @@ -154,6 +177,12 @@ void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* model glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); } +DrawTextureProgram::DrawTextureProgram(): + DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) { + texCoords = addAttrib("texCoords"); + sampler = addUniform("sampler"); +} + /////////////////////////////////////////////////////////////////////////////// // Support /////////////////////////////////////////////////////////////////////////////// @@ -175,6 +204,7 @@ OpenGLRenderer::OpenGLRenderer() { LOGD("Create OpenGLRenderer"); mDrawColorShader = new DrawColorProgram; + mDrawTextureShader = new DrawTextureProgram; } OpenGLRenderer::~OpenGLRenderer() { @@ -252,17 +282,90 @@ int OpenGLRenderer::saveSnapshot() { bool OpenGLRenderer::restoreSnapshot() { bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; + bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer; - mSaveCount--; - - // Do not merge these two lines! + sp<Snapshot> current = mSnapshot; sp<Snapshot> previous = mSnapshot->previous; + + if (restoreLayer) { + // Unbind current FBO and restore previous one + // Most of the time, previous->fbo will be 0 to bind the default buffer + glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); + + const Rect& layer = current->layer; + clipRect(layer.left, layer.top, layer.right, layer.bottom); + mSnapshot->transform.loadIdentity(); + + drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha); + + glDeleteFramebuffers(1, ¤t->fbo); + glDeleteTextures(1, ¤t->texture); + } + mSnapshot = previous; + mSaveCount--; return restoreClip; } /////////////////////////////////////////////////////////////////////////////// +// Layers +/////////////////////////////////////////////////////////////////////////////// + +int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, + const SkPaint* p, int flags) { + // TODO Implement + return saveSnapshot(); +} + +int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, + int alpha, int flags) { + int count = saveSnapshot(); + + mSnapshot->flags |= Snapshot::kFlagIsLayer; + mSnapshot->alpha = alpha / 255.0f; + mSnapshot->layer.set(left, top, right, bottom); + + // Generate the FBO and attach the texture + glGenFramebuffers(1, &mSnapshot->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, mSnapshot->fbo); + + // Generate the texture in which the FBO will draw + glGenTextures(1, &mSnapshot->texture); + glBindTexture(GL_TEXTURE_2D, mSnapshot->texture); + + // The FBO will not be scaled, so we can use lower quality filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // TODO ***** IMPORTANT ***** + // Creating a texture-backed FBO works only if the texture is the same size + // as the original rendering buffer (in this case, mWidth and mHeight.) + // This is expensive and wasteful and must be fixed. + + const GLsizei width = mWidth; //right - left; + const GLsizei height = mHeight; //bottom - right; + + const GLint format = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) ? GL_RGBA : GL_RGB; + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + // Bind texture to FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mSnapshot->texture, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LOGD("Framebuffer incomplete %d", status); + + glDeleteFramebuffers(1, &mSnapshot->fbo); + glDeleteTextures(1, &mSnapshot->texture); + } + + return count; +} + +/////////////////////////////////////////////////////////////////////////////// // Transforms /////////////////////////////////////////////////////////////////////////////// @@ -346,10 +449,10 @@ void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color); } -void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* paint) { +void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { // TODO Support more than just color // TODO: Set the transfer mode - drawColorRect(left, top, right, bottom, paint->getColor()); + drawColorRect(left, top, right, bottom, p->getColor()); } void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) { @@ -375,5 +478,43 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot glDisableVertexAttribArray(mDrawColorShader->position); } +void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, + GLuint texture, float alpha) { + mModelView.loadTranslate(left, top, 0.0f); + mModelView.scale(right - left, bottom - top, 1.0f); + + mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]); + + // TODO Correctly set the blend function + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + glBindTexture(GL_TEXTURE_2D, texture); + + glActiveTexture(GL_TEXTURE0); + glUniform1i(mDrawTextureShader->sampler, 0); + + const GLvoid* p = &gDrawTextureVertices[0].position[0]; + const GLvoid* t = &gDrawTextureVertices[0].texture[0]; + + glEnableVertexAttribArray(mDrawTextureShader->position); + glVertexAttribPointer(mDrawTextureShader->position, 2, GL_FLOAT, GL_FALSE, + gDrawTextureVertexStride, p); + + glEnableVertexAttribArray(mDrawTextureShader->texCoords); + glVertexAttribPointer(mDrawTextureShader->texCoords, 2, GL_FLOAT, GL_FALSE, + gDrawTextureVertexStride, t); + + glVertexAttrib4f(mDrawTextureShader->color, 1.0f, 1.0f, 1.0f, alpha); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount); + + glDisableVertexAttribArray(mDrawTextureShader->position); + glDisableVertexAttribArray(mDrawTextureShader->texCoords); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_BLEND); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 6f6b997bd81e..527bf3e46308 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -45,12 +45,17 @@ public: transform(s->transform), clipRect(s->clipRect), flags(kFlagDirtyTransform), - previous(s) { + previous(s), + layer(0.0f, 0.0f, 0.0f, 0.0f), + texture(0), + fbo(0), + alpha(255) { } enum Flags { kFlagClipSet = 0x1, kFlagDirtyTransform = 0x2, + kFlagIsLayer = 0x4, }; const Rect& getMappedClip(); @@ -67,6 +72,12 @@ public: // Previous snapshot in the frames stack sp<Snapshot> previous; + // Layer, only set if kFlagIsLayer is set + Rect layer; + GLuint texture; + GLuint fbo; + float alpha; + private: // Clipping rectangle mapped with the transform Rect mappedClip; @@ -76,7 +87,10 @@ struct SimpleVertex { float position[2]; }; // struct SimpleVertex -typedef char* shader; +struct TextureVertex { + float position[2]; + float texture[2]; +}; // struct TextureVertex class Program: public LightRefBase<Program> { public: @@ -110,6 +124,7 @@ private: class DrawColorProgram: public Program { public: DrawColorProgram(); + DrawColorProgram(const char* vertex, const char* fragment); void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix); @@ -120,6 +135,17 @@ public: int projection; int modelView; int transform; + +protected: + void getAttribsAndUniforms(); +}; + +class DrawTextureProgram: public DrawColorProgram { +public: + DrawTextureProgram(); + + int sampler; + int texCoords; }; /////////////////////////////////////////////////////////////////////////////// @@ -139,6 +165,9 @@ public: void restore(); void restoreToCount(int saveCount); + int saveLayer(float left, float top, float right, float bottom, const SkPaint* p, int flags); + int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags); + void translate(float dx, float dy); void rotate(float degrees); void scale(float sx, float sy); @@ -152,7 +181,7 @@ public: bool clipRect(float left, float top, float right, float bottom); void drawColor(int color, SkXfermode::Mode mode); - void drawRect(float left, float top, float right, float bottom, SkPaint* paint); + void drawRect(float left, float top, float right, float bottom, const SkPaint* paint); private: int saveSnapshot(); @@ -161,6 +190,8 @@ private: void setScissorFromClip(); void drawColorRect(float left, float top, float right, float bottom, int color); + void drawTextureRect(float left, float top, float right, float bottom, GLuint texture, + float alpha); // Dimensions of the drawing surface int mWidth, mHeight; @@ -180,6 +211,7 @@ private: // Shaders sp<DrawColorProgram> mDrawColorShader; + sp<DrawTextureProgram> mDrawTextureShader; }; // class OpenGLRenderer }; // namespace uirenderer diff --git a/libs/hwui/shaders/drawColor.frag b/libs/hwui/shaders/drawColor.frag index f753abbb09ea..e84c47bb6f33 100644 --- a/libs/hwui/shaders/drawColor.frag +++ b/libs/hwui/shaders/drawColor.frag @@ -1,8 +1,6 @@ SHADER_SOURCE(gDrawColorFragmentShader, -precision mediump float; - -varying vec4 outColor; +varying lowp vec4 outColor; void main(void) { gl_FragColor = outColor; diff --git a/libs/hwui/shaders/drawTexture.frag b/libs/hwui/shaders/drawTexture.frag new file mode 100644 index 000000000000..5bd420eea7f0 --- /dev/null +++ b/libs/hwui/shaders/drawTexture.frag @@ -0,0 +1,12 @@ +SHADER_SOURCE(gDrawTextureFragmentShader, + +varying lowp vec4 outColor; +varying mediump vec2 outTexCoords; + +uniform sampler2D sampler; + +void main(void) { + gl_FragColor = texture2D(sampler, outTexCoords) * outColor; +} + +); diff --git a/libs/hwui/shaders/drawTexture.vert b/libs/hwui/shaders/drawTexture.vert new file mode 100644 index 000000000000..310a81249c97 --- /dev/null +++ b/libs/hwui/shaders/drawTexture.vert @@ -0,0 +1,20 @@ +SHADER_SOURCE(gDrawTextureVertexShader, + +attribute vec4 position; +attribute vec2 texCoords; +attribute vec4 color; + +uniform mat4 projection; +uniform mat4 modelView; +uniform mat4 transform; + +varying vec4 outColor; +varying vec2 outTexCoords; + +void main(void) { + outColor = color; + outTexCoords = texCoords; + gl_Position = projection * transform * modelView * position; +} + +); diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java index 14154a8894f4..85e399700e26 100644 --- a/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java +++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java @@ -22,7 +22,11 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.os.Bundle; import android.util.Log; +import android.view.Gravity; import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.FrameLayout; @SuppressWarnings({"UnusedDeclaration"}) public class HwUiActivity extends Activity { @@ -32,7 +36,19 @@ public class HwUiActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(new DirtyBitmapView(this)); + DirtyBitmapView container = new DirtyBitmapView(this); + + ColorView color = new ColorView(this); + container.addView(color, new DirtyBitmapView.LayoutParams( + dipToPx(this, 100), dipToPx(this, 100), Gravity.CENTER)); + + AlphaAnimation a = new AlphaAnimation(1.0f, 0.0f); + a.setDuration(2000); + a.setRepeatCount(Animation.INFINITE); + a.setRepeatMode(Animation.REVERSE); + color.startAnimation(a); + + setContentView(container); } @SuppressWarnings({"UnusedDeclaration"}) @@ -40,7 +56,19 @@ public class HwUiActivity extends Activity { return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f); } - static class DirtyBitmapView extends View { + static class ColorView extends View { + ColorView(Context c) { + super(c); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawRGB(0, 255, 0); + } + } + + static class DirtyBitmapView extends FrameLayout { private final Paint mPaint; DirtyBitmapView(Context c) { @@ -49,9 +77,7 @@ public class HwUiActivity extends Activity { } @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - + public void dispatchDraw(Canvas canvas) { canvas.drawRGB(255, 255, 255); mPaint.setColor(0xffff0000); @@ -86,6 +112,7 @@ public class HwUiActivity extends Activity { Canvas.EdgeType.BW)); canvas.restore(); + canvas.save(); canvas.scale(2.0f, 2.0f); canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f); @@ -94,6 +121,21 @@ public class HwUiActivity extends Activity { mPaint.setColor(0xff0000ff); canvas.drawRect(20.0f, 0.0f, 40.0f, 20.0f, mPaint); + + canvas.restore(); + + final int restoreTo = canvas.save(); + canvas.saveLayerAlpha(0.0f, 100.0f, getWidth(), 150.0f, 127, + Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); + mPaint.setColor(0xff0000ff); + canvas.drawRect(0.0f, 100.0f, 40.0f, 150.0f, mPaint); + mPaint.setColor(0xff00ffff); + canvas.drawRect(40.0f, 100.0f, 140.0f, 150.0f, mPaint); + mPaint.setColor(0xffff00ff); + canvas.drawRect(140.0f, 100.0f, 240.0f, 150.0f, mPaint); + canvas.restoreToCount(restoreTo); + + super.dispatchDraw(canvas); } } } |