Improve GL draw circle

This commit is contained in:
seven332 committed 2015-08-02 00:13:44 +08:00
1 parent 5e2f51531d
commit ca2a55fd12
6 files changed
+105 -55

No files matched your search

@@ -86,13 +86,24 @@ public interface GLCanvas {
// (Both end points are included).
void drawRect(float x1, float y1, float x2, float y2, GLPaint paint);
// Draws a oval using the specified paint for (cx, cy, radiusX, radiusY)
// (Both end points are included).
void drawOval(float cx, float cy, float radiusX, float radiusY,
GLPaint paint);
// Draw a arc inside a rect
void drawArc(float x, float y, float width, float height, float startAngle,
void drawArc(float cx, float cy, float radiusX, float radiusY,
float sweepAngle, GLPaint paint);
// Fills the specified rectangle with the specified color.
void fillRect(float x, float y, float width, float height, int color);
// Fills the specified oval with the specified color.
void fillOval(float cx, float cy, float radiusX, float radiusY, int color);
// Fills the specified sector with the specified color.
void fillSector(float cx, float cy, float radiusX, float radiusY, float sweepAngle, int color);
// Draws a texture to the specified rectangle.
void drawTexture(BasicTexture texture, int x, int y, int width, int height);
@@ -192,8 +192,12 @@ public class GLES11Canvas implements GLCanvas {
}
@Override
public void drawArc(float x, float y, float width, float height,
float startAngle, float sweepAngle, GLPaint paint) {
public void drawOval(float cx, float cy, float radiusX, float radiusY, GLPaint paint) {
// TODO
}
@Override
public void drawArc(float cx, float cy, float radiusX, float radiusY, float sweepAngle, GLPaint paint) {
// TODO
}
@@ -231,6 +235,16 @@ public class GLES11Canvas implements GLCanvas {
mCountFillRect++;
}
@Override
public void fillOval(float x, float y, float width, float height, int color) {
// TODO
}
@Override
public void fillSector(float cx, float cy, float radiusX, float radiusY, float sweepAngle, int color) {
// TODO
}
@Override
public void translate(float x, float y, float z) {
Matrix.translateM(mMatrixValues, 0, x, y, z);
@@ -49,7 +49,8 @@ public class GLES20Canvas implements GLCanvas {
private static final int OFFSET_FILL_RECT = 0;
private static final int OFFSET_DRAW_LINE = OFFSET_FILL_RECT + COUNT_FILL_VERTEX;
private static final int OFFSET_DRAW_RECT = OFFSET_DRAW_LINE + COUNT_LINE_VERTEX;
private static final int OFFSET_DRAW_CIRCLE = OFFSET_DRAW_RECT + COUNT_RECT_VERTEX;
private static final int OFFSET_FILL_CIRCLE = OFFSET_DRAW_RECT + COUNT_RECT_VERTEX;
private static final int OFFSET_DRAW_CIRCLE = OFFSET_FILL_CIRCLE + 1;
private static final int OFFSET_LAST = OFFSET_DRAW_CIRCLE + COUNT_CIRCLE_VERTEX + 1;
private static final float[] BOX_COORDINATES = new float[OFFSET_LAST * 2];
@@ -65,7 +66,8 @@ public class GLES20Canvas implements GLCanvas {
0, 0, // Draw rectangle outline
0, 1,
1, 1,
1, 0
1, 0,
0.5f, 0.5f // Fill circle
};
System.arraycopy(temp, 0, BOX_COORDINATES, 0, temp.length);
@@ -514,31 +516,18 @@ public class GLES20Canvas implements GLCanvas {
}
@Override
public void drawArc(float x, float y, float width, float height, float startAngle,
float sweepAngle, GLPaint paint) {
if (Math.abs(Math.round(COUNT_CIRCLE_VERTEX * sweepAngle / 360)) >= COUNT_CIRCLE_VERTEX) {
// It is a circle
draw(GLES20.GL_LINE_LOOP, OFFSET_DRAW_CIRCLE, COUNT_CIRCLE_VERTEX, x, y, width, height, paint);
} else {
if (sweepAngle < 0) {
startAngle += sweepAngle;
sweepAngle = - sweepAngle;
}
startAngle = MathUtils.positiveModulo(startAngle, 360);
public void drawOval(float cx, float cy, float radiusX, float radiusY, GLPaint paint) {
float halfLineWidth = paint.getLineWidth() / 2;
fillOval(cx, cy, radiusX + halfLineWidth, radiusY + halfLineWidth, paint.getColor());
fillOval(cx, cy, radiusX - halfLineWidth, radiusY - halfLineWidth, paint.getBackgroundColor());
}
float stopAngle = startAngle + sweepAngle;
if (stopAngle > 360) {
int start = OFFSET_DRAW_CIRCLE + Math.round(COUNT_CIRCLE_VERTEX * startAngle / 360);
draw(GLES20.GL_LINE_STRIP, start, OFFSET_LAST - start, x, y, width, height, paint);
int stop = Math.round(COUNT_CIRCLE_VERTEX * (stopAngle - 360) / 360) + 1;
draw(GLES20.GL_LINE_STRIP, OFFSET_DRAW_CIRCLE, stop, x, y, width, height, paint);
} else {
int start = OFFSET_DRAW_CIRCLE + Math.round(COUNT_CIRCLE_VERTEX * startAngle / 360);
int count = Math.round(COUNT_CIRCLE_VERTEX * sweepAngle / 360) + 1;
draw(GLES20.GL_LINE_STRIP, start, count, x, y, width, height, paint);
}
}
mCountDrawLine++;
@Override
public void drawArc(float cx, float cy, float radiusX, float radiusY,
float sweepAngle, GLPaint paint) {
float halfLineWidth = paint.getLineWidth() / 2;
fillSector(cx, cy, radiusX + halfLineWidth, radiusY + halfLineWidth, sweepAngle, paint.getColor());
fillSector(cx, cy, radiusX - halfLineWidth, radiusY - halfLineWidth, sweepAngle, paint.getBackgroundColor());
}
private void draw(int type, int offset, int count, float x, float y, float width, float height,
@@ -631,6 +620,27 @@ public class GLES20Canvas implements GLCanvas {
mCountFillRect++;
}
@Override
public void fillOval(float cx, float cy, float radiusX, float radiusY, int color) {
draw(GLES20.GL_TRIANGLE_FAN, OFFSET_FILL_CIRCLE, OFFSET_LAST - OFFSET_FILL_CIRCLE,
cx - radiusX, cy - radiusY, radiusX * 2, radiusY * 2, color, 0f);
mCountFillRect++;
}
@Override
public void fillSector(float cx, float cy, float radiusX, float radiusY, float sweepAngle, int color) {
float conjugateAngle = Math.abs(360 - MathUtils.positiveModulo(sweepAngle, 360));
int conjugateCount = Math.round(COUNT_CIRCLE_VERTEX * conjugateAngle / 360);
if (conjugateCount == 0) {
// It is a circle
fillOval(cx, cy, radiusX, radiusY, color);
} else if (conjugateCount < COUNT_CIRCLE_VERTEX) {
draw(GLES20.GL_TRIANGLE_FAN, OFFSET_FILL_CIRCLE, OFFSET_LAST - OFFSET_FILL_CIRCLE - conjugateCount,
cx - radiusX, cy - radiusY, radiusX * 2, radiusY * 2, color, 0f);
mCountFillRect++;
}
}
@Override
public void drawTexture(BasicTexture texture, int x, int y, int width, int height) {
if (width <= 0 || height <= 0) {
@@ -21,6 +21,7 @@ import junit.framework.Assert;
public class GLPaint {
private float mLineWidth = 1f;
private int mColor = 0;
private int mBackgroundColor = 0;
public void setColor(int color) {
mColor = color;
@@ -30,6 +31,14 @@ public class GLPaint {
return mColor;
}
public void setBackgroundColor(int backgroundColor) {
mBackgroundColor = backgroundColor;
}
public int getBackgroundColor() {
return mBackgroundColor;
}
public void setLineWidth(float width) {
Assert.assertTrue(width >= 0);
mLineWidth = width;
@@ -25,6 +25,8 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener {
private static final int MAX_SETTLE_DURATION = 600; // ms
public static final int BACKGROUND_COLOR = 0xff212121;
private static final int UNKNOWN_SEEN = 0;
private static final int SEEN = 1;
private static final int UNSEEN = 2;
@@ -23,10 +23,10 @@ public class ProgressView extends GLView {
private GLPaint mGLPaint;
private float mItemX;
private float mItemY;
private float mItemWidth;
private float mItemHeight;
private float mCx;
private float mCy;
private float mRadiusX;
private float mRadiusY;
private float mStartTrim = 0.0f;
private float mEndTrim = 0.0f;
@@ -40,6 +40,7 @@ public class ProgressView extends GLView {
public ProgressView() {
mGLPaint = new GLPaint();
mGLPaint.setColor(Color.WHITE);
mGLPaint.setBackgroundColor(GalleryView.BACKGROUND_COLOR);
mAnimations = new ArrayList<>();
setupAnimations();
@@ -114,10 +115,10 @@ public class ProgressView extends GLView {
int width = right - left;
int height = bottom - top;
mGLPaint.setLineWidth(Math.min(width, height) / 12.0f);
mItemX = width / 48.0f * 5.0f;
mItemY = height / 48.0f * 5.0f;
mItemWidth = width / 48.0f * 38.0f;
mItemHeight = height / 48.0f * 38.0f;
mCx = width / 2;
mCy = height / 2;
mRadiusX = width / 48.0f * 19.0f;
mRadiusY = height / 48.0f * 19.0f;
}
public void setColor(int color) {
@@ -143,10 +144,10 @@ public class ProgressView extends GLView {
public void setProgress(float progress) {
if (!mIndeterminate) {
mStartTrim = -0.25f;
mEndTrim = progress - 0.25f;
mStartTrim = 0;
mEndTrim = progress;
mTrimRotation = 0.0f;
mCanvasRotation = 0.0f;
mCanvasRotation = -90f;
invalidate();
}
}
@@ -155,32 +156,35 @@ public class ProgressView extends GLView {
protected void onRender(GLCanvas canvas) {
update();
canvas.save();
int width = getWidth();
int height = getHeight();
int cx = width / 2;
int cy = height / 2;
float startAngle = (mStartTrim + mTrimRotation) * 360.0f;
float endAngle = (mEndTrim + mTrimRotation) * 360.0f;
float sweepAngle = endAngle - startAngle;
if (mIndeterminate) {
float diameter = Math.min(mRadiusX, mRadiusY) * 2;
float minAngle = Math.max((float) (360.0D / (diameter * 3.141592653589793D)), 3f);
if ((sweepAngle < minAngle) && (sweepAngle > -minAngle)) {
float symbol = Math.signum(sweepAngle);
sweepAngle = (Math.abs(symbol) == 1f ? symbol : 1f) * minAngle;
}
}
canvas.save();
float rotation = MathUtils.positiveModulo(mCanvasRotation + startAngle, 360);
canvas.translate(cx, cy);
canvas.rotate(mCanvasRotation, 0, 0, 1);
if (mCanvasRotation % 180 != 0) {
canvas.rotate(rotation, 0, 0, 1);
if (rotation % 180 != 0) {
canvas.translate(-cy, -cx);
} else {
canvas.translate(-cx, -cy);
}
float startAngle = (mStartTrim + mTrimRotation) * 360.0f;
float endAngle = (mEndTrim + mTrimRotation) * 360.0f;
float sweepAngle = endAngle - startAngle;
if (mIndeterminate) {
float diameter = Math.min(mItemWidth, mItemHeight);
float minAngle = (float) (360.0D / (diameter * 3.141592653589793D / 4));
if ((sweepAngle < minAngle) && (sweepAngle > -minAngle)) {
sweepAngle = Math.signum(sweepAngle) * minAngle;
}
}
canvas.drawArc(mItemX, mItemY, mItemWidth, mItemHeight, startAngle, sweepAngle, mGLPaint);
canvas.drawArc(mCx, mCy, mRadiusX, mRadiusY, sweepAngle, mGLPaint);
canvas.restore();
}