OSDN Git Service

Add support for arcs.
authorRomain Guy <romainguy@google.com>
Mon, 24 Jan 2011 00:15:02 +0000 (16:15 -0800)
committerRomain Guy <romainguy@google.com>
Mon, 24 Jan 2011 00:15:02 +0000 (16:15 -0800)
Change-Id: I96c057ff4eb1b464b03f132da0b85333777bee4f

core/java/android/view/GLES20Canvas.java
core/jni/android_view_GLES20Canvas.cpp
libs/hwui/Caches.h
libs/hwui/DisplayListRenderer.cpp
libs/hwui/DisplayListRenderer.h
libs/hwui/OpenGLRenderer.cpp
libs/hwui/OpenGLRenderer.h
libs/hwui/ShapeCache.cpp
libs/hwui/ShapeCache.h
tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java

index 936e9d2..f6c5e0b 100644 (file)
@@ -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));
index 2daffbb..8d074af 100644 (file)
@@ -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 },
 
index 3bac422..0a9335f 100644 (file)
@@ -164,6 +164,7 @@ public:
     CircleShapeCache circleShapeCache;
     OvalShapeCache ovalShapeCache;
     RectShapeCache rectShapeCache;
+    ArcShapeCache arcShapeCache;
     PatchCache patchCache;
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
index 8714997..200e248 100644 (file)
@@ -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);
index 8183e25..35bb163 100644 (file)
@@ -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);
index 99c0600..2467d8e 100644 (file)
@@ -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;
index 30cf102..eec3750 100644 (file)
@@ -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,
index da86075..0d7cd9c 100644 (file)
@@ -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
index a4aff9d..e535466 100644 (file)
@@ -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
 ///////////////////////////////////////////////////////////////////////////////
index ddf43d7..97e5526 100644 (file)
@@ -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();
         }
     }
 }