From ca2a55fd12e67c9fae92c092e64eeda5701fa570 Mon Sep 17 00:00:00 2001 From: seven332 Date: Sun, 2 Aug 2015 00:13:44 +0800 Subject: [PATCH] Improve GL draw circle --- .../ehviewer/gallery/glrenderer/GLCanvas.java | 13 +++- .../gallery/glrenderer/GLES11Canvas.java | 18 +++++- .../gallery/glrenderer/GLES20Canvas.java | 62 +++++++++++-------- .../ehviewer/gallery/glrenderer/GLPaint.java | 9 +++ .../ehviewer/gallery/ui/GalleryView.java | 2 + .../ehviewer/gallery/ui/ProgressView.java | 56 +++++++++-------- 6 files changed, 105 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java index 0c8bbc0d4..239608f0d 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java @@ -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); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java index 9ebd3ef0b..115dcfed7 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java @@ -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); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java index d30053903..88d1cd87c 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java @@ -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) { diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java index cc66494fd..887dbd781 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java @@ -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; diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ui/GalleryView.java b/app/src/main/java/com/hippo/ehviewer/gallery/ui/GalleryView.java index 8e75882ab..60d68d670 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ui/GalleryView.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ui/GalleryView.java @@ -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; diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java b/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java index 4b9c0d53f..729569c50 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ui/ProgressView.java @@ -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(); }