diff options
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 8 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/Caches.h | 1 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 15 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 3 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 15 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 2 | ||||
-rw-r--r-- | libs/hwui/ShapeCache.cpp | 31 | ||||
-rw-r--r-- | libs/hwui/ShapeCache.h | 60 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java | 26 |
10 files changed, 167 insertions, 2 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 936e9d2413f2..f6c5e0bc2ad3 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -525,9 +525,15 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) { - // TODO: Implement + boolean hasModifier = setupModifiers(paint); + nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, + useCenter, paint.mNativePaint); + if (hasModifier) nResetModifiers(mRenderer); } + private native void nDrawArc(int renderer, float left, float top, float right, float bottom, + float startAngle, float sweepAngle, boolean useCenter, int paint); + @Override public void drawARGB(int a, int r, int g, int b) { drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 2daffbb47416..8d074afb5dae 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -332,6 +332,12 @@ static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject canvas, renderer->drawOval(left, top, right, bottom, paint); } +static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, + jfloat startAngle, jfloat sweepAngle, jboolean useCenter, SkPaint* paint) { + renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); +} + static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, SkRegion* region, SkPaint* paint) { SkRegion::Iterator it(*region); @@ -609,6 +615,8 @@ static JNINativeMethod gMethods[] = { { "nDrawRoundRect", "(IFFFFFFI)V", (void*) android_view_GLES20Canvas_drawRoundRect }, { "nDrawCircle", "(IFFFI)V", (void*) android_view_GLES20Canvas_drawCircle }, { "nDrawOval", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawOval }, + { "nDrawArc", "(IFFFFFFZI)V", (void*) android_view_GLES20Canvas_drawArc }, + { "nDrawPath", "(III)V", (void*) android_view_GLES20Canvas_drawPath }, { "nDrawLines", "(I[FIII)V", (void*) android_view_GLES20Canvas_drawLines }, diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 3bac422015c5..0a9335f23288 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -164,6 +164,7 @@ public: CircleShapeCache circleShapeCache; OvalShapeCache ovalShapeCache; RectShapeCache rectShapeCache; + ArcShapeCache arcShapeCache; PatchCache patchCache; TextDropShadowCache dropShadowCache; FboCache fboCache; diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 871499703667..200e24800291 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -108,6 +108,7 @@ const char* DisplayList::OP_NAMES[] = { "DrawRoundRect", "DrawCircle", "DrawOval", + "DrawArc", "DrawPath", "DrawLines", "DrawText", @@ -363,6 +364,11 @@ void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) { renderer.drawOval(getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); } break; + case DrawArc: { + renderer.drawArc(getFloat(), getFloat(), getFloat(), getFloat(), + getFloat(), getFloat(), getInt() == 1, getPaint()); + } + break; case DrawPath: { renderer.drawPath(getPath(), getPaint()); } @@ -675,6 +681,15 @@ void DisplayListRenderer::drawOval(float left, float top, float right, float bot addPaint(paint); } +void DisplayListRenderer::drawArc(float left, float top, float right, float bottom, + float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { + addOp(DisplayList::DrawOval); + addBounds(left, top, right, bottom); + addPoint(startAngle, sweepAngle); + addInt(useCenter ? 1 : 0); + addPaint(paint); +} + void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) { addOp(DisplayList::DrawPath); addPath(path); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 8183e253b452..35bb163f9c62 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -114,6 +114,7 @@ public: DrawRoundRect, DrawCircle, DrawOval, + DrawArc, DrawPath, DrawLines, DrawText, @@ -281,6 +282,8 @@ public: float rx, float ry, SkPaint* paint); void drawCircle(float x, float y, float radius, SkPaint* paint); void drawOval(float left, float top, float right, float bottom, SkPaint* paint); + void drawArc(float left, float top, float right, float bottom, + float startAngle, float sweepAngle, bool useCenter, SkPaint* paint); void drawPath(SkPath* path, SkPaint* paint); void drawLines(float* points, int count, SkPaint* paint); void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 99c0600ae3eb..2467d8ef7943 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1396,6 +1396,21 @@ void OpenGLRenderer::drawOval(float left, float top, float right, float bottom, drawShape(left, top, texture, paint); } +void OpenGLRenderer::drawArc(float left, float top, float right, float bottom, + float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { + if (mSnapshot->isIgnored()) return; + + if (fabs(sweepAngle) >= 360.0f) { + drawOval(left, top, right, bottom, paint); + return; + } + + glActiveTexture(gTextureUnits[0]); + const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top, + startAngle, sweepAngle, useCenter, paint); + drawShape(left, top, texture, paint); +} + void OpenGLRenderer::drawRectAsShape(float left, float top, float right, float bottom, SkPaint* paint) { if (mSnapshot->isIgnored()) return; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 30cf10224e9d..eec37501784d 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -113,6 +113,8 @@ public: float rx, float ry, SkPaint* paint); virtual void drawCircle(float x, float y, float radius, SkPaint* paint); virtual void drawOval(float left, float top, float right, float bottom, SkPaint* paint); + virtual void drawArc(float left, float top, float right, float bottom, + float startAngle, float sweepAngle, bool useCenter, SkPaint* paint); virtual void drawPath(SkPath* path, SkPaint* paint); virtual void drawLines(float* points, int count, SkPaint* paint); virtual void drawText(const char* text, int bytesCount, int count, float x, float y, diff --git a/libs/hwui/ShapeCache.cpp b/libs/hwui/ShapeCache.cpp index da86075602bc..0d7cd9cb9a72 100644 --- a/libs/hwui/ShapeCache.cpp +++ b/libs/hwui/ShapeCache.cpp @@ -114,5 +114,36 @@ PathTexture* RectShapeCache::getRect(float width, float height, SkPaint* paint) return texture; } +/////////////////////////////////////////////////////////////////////////////// +// Arcs +/////////////////////////////////////////////////////////////////////////////// + +ArcShapeCache::ArcShapeCache(): ShapeCache<ArcShapeCacheEntry>( + "arc", PROPERTY_SHAPE_CACHE_SIZE, DEFAULT_SHAPE_CACHE_SIZE) { +} + +PathTexture* ArcShapeCache::getArc(float width, float height, + float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { + ArcShapeCacheEntry entry(width, height, startAngle, sweepAngle, useCenter, paint); + PathTexture* texture = get(entry); + + if (!texture) { + SkPath path; + SkRect r; + r.set(0.0f, 0.0f, width, height); + if (useCenter) { + path.moveTo(r.centerX(), r.centerY()); + } + path.arcTo(r, startAngle, sweepAngle, !useCenter); + if (useCenter) { + path.close(); + } + + texture = addTexture(entry, &path, paint); + } + + return texture; +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index a4aff9df117c..e53546605f13 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -281,6 +281,58 @@ private: uint32_t mHeight; }; // RectShapeCacheEntry +struct ArcShapeCacheEntry: public ShapeCacheEntry { + ArcShapeCacheEntry(float width, float height, float startAngle, float sweepAngle, + bool useCenter, SkPaint* paint): + ShapeCacheEntry(ShapeCacheEntry::kShapeArc, paint) { + mWidth = *(uint32_t*) &width; + mHeight = *(uint32_t*) &height; + mStartAngle = *(uint32_t*) &startAngle; + mSweepAngle = *(uint32_t*) &sweepAngle; + mUseCenter = useCenter ? 1 : 0; + } + + ArcShapeCacheEntry(): ShapeCacheEntry() { + mWidth = 0; + mHeight = 0; + mStartAngle = 0; + mSweepAngle = 0; + mUseCenter = 0; + } + + ArcShapeCacheEntry(const ArcShapeCacheEntry& entry): + ShapeCacheEntry(entry) { + mWidth = entry.mWidth; + mHeight = entry.mHeight; + mStartAngle = entry.mStartAngle; + mSweepAngle = entry.mSweepAngle; + mUseCenter = entry.mUseCenter; + } + + bool lessThan(const ShapeCacheEntry& r) const { + const ArcShapeCacheEntry& rhs = (const ArcShapeCacheEntry&) r; + LTE_INT(mWidth) { + LTE_INT(mHeight) { + LTE_INT(mStartAngle) { + LTE_INT(mSweepAngle) { + LTE_INT(mUseCenter) { + return false; + } + } + } + } + } + return false; + } + +private: + uint32_t mWidth; + uint32_t mHeight; + uint32_t mStartAngle; + uint32_t mSweepAngle; + uint32_t mUseCenter; +}; // ArcShapeCacheEntry + /** * A simple LRU shape cache. The cache has a maximum size expressed in bytes. * Any texture added to the cache causing the cache to grow beyond the maximum @@ -370,6 +422,14 @@ public: PathTexture* getRect(float width, float height, SkPaint* paint); }; // class RectShapeCache +class ArcShapeCache: public ShapeCache<ArcShapeCacheEntry> { +public: + ArcShapeCache(); + + PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, + bool useCenter, SkPaint* paint); +}; // class ArcShapeCache + /////////////////////////////////////////////////////////////////////////////// // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java index ddf43d77739e..97e55269b128 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java @@ -39,6 +39,7 @@ public class ShapesActivity extends Activity { private Paint mFillPaint; private RectF mRect; private RectF mOval; + private RectF mArc; ShapesView(Context c) { super(c); @@ -63,6 +64,7 @@ public class ShapesActivity extends Activity { mFillPaint.setStyle(Paint.Style.FILL); mOval = new RectF(0.0f, 0.0f, 80.0f, 45.0f); + mArc = new RectF(0.0f, 0.0f, 100.0f, 120.0f); } @Override @@ -103,7 +105,7 @@ public class ShapesActivity extends Activity { canvas.restore(); canvas.save(); - canvas.translate(650.0f, 50.0f); + canvas.translate(625.0f, 50.0f); canvas.drawRect(0.0f, 0.0f, 160.0f, 90.0f, mNormalPaint); canvas.translate(0.0f, 110.0f); @@ -112,6 +114,28 @@ public class ShapesActivity extends Activity { canvas.translate(0.0f, 110.0f); canvas.drawRect(0.0f, 0.0f, 160.0f, 90.0f, mFillPaint); canvas.restore(); + + canvas.save(); + canvas.translate(825.0f, 50.0f); + canvas.drawArc(mArc, -30.0f, 70.0f, true, mNormalPaint); + + canvas.translate(0.0f, 110.0f); + canvas.drawArc(mArc, -30.0f, 70.0f, true, mStrokePaint); + + canvas.translate(0.0f, 110.0f); + canvas.drawArc(mArc, -30.0f, 70.0f, true, mFillPaint); + canvas.restore(); + + canvas.save(); + canvas.translate(950.0f, 50.0f); + canvas.drawArc(mArc, 30.0f, 100.0f, false, mNormalPaint); + + canvas.translate(0.0f, 110.0f); + canvas.drawArc(mArc, 30.0f, 100.0f, false, mStrokePaint); + + canvas.translate(0.0f, 110.0f); + canvas.drawArc(mArc, 30.0f, 100.0f, false, mFillPaint); + canvas.restore(); } } } |