@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));
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);
{ "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 },
CircleShapeCache circleShapeCache;
OvalShapeCache ovalShapeCache;
RectShapeCache rectShapeCache;
+ ArcShapeCache arcShapeCache;
PatchCache patchCache;
TextDropShadowCache dropShadowCache;
FboCache fboCache;
"DrawRoundRect",
"DrawCircle",
"DrawOval",
+ "DrawArc",
"DrawPath",
"DrawLines",
"DrawText",
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());
}
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);
DrawRoundRect,
DrawCircle,
DrawOval,
+ DrawArc,
DrawPath,
DrawLines,
DrawText,
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);
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;
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,
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
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
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
///////////////////////////////////////////////////////////////////////////////
private Paint mFillPaint;
private RectF mRect;
private RectF mOval;
+ private RectF mArc;
ShapesView(Context c) {
super(c);
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
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);
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();
}
}
}