Add support for arcs.

Change-Id: I96c057ff4eb1b464b03f132da0b85333777bee4f
This commit is contained in:
Romain Guy
2011-01-23 16:15:02 -08:00
parent c1cd9ba335
commit 8b2f5267f1
10 changed files with 167 additions and 2 deletions

View 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));

View 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 },

View File

@ -164,6 +164,7 @@ public:
CircleShapeCache circleShapeCache;
OvalShapeCache ovalShapeCache;
RectShapeCache rectShapeCache;
ArcShapeCache arcShapeCache;
PatchCache patchCache;
TextDropShadowCache dropShadowCache;
FboCache fboCache;

View 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);

View 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);

View 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;

View 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,

View 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

View 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
///////////////////////////////////////////////////////////////////////////////

View 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();
}
}
}