Path drawn on scaled GLES20RecordingCanvas
has quality as if it was drawn unscaled in bitmap and then up-scaled.
In contrast, if I create Canvas
with backing bitmap and then apply the same scaling transformations to Canvas
object I get much superior bitmap.
Here both circles are drawn with Path.addCircle
and using Canvas.scale
. Upper circle is drawn with scaled GLES20RecordingCanvas
and lower is drawn with scaled simple Canvas
with backing bitmap.
Some code:
public class TestPathRenderer extends View {
...
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
float distortedWidth = getDistortedWidth();
float distortedHeight = getDistortedHeight();
path.reset();
path.addCircle(distortedWidth/2f, distortedHeight/2f, Math.min(distortedWidth/2f, distortedHeight/2f), Path.Direction.CW);
bitmap = assembleNewBitmap(measuredWidth, measuredHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (renderMode) {
case RENDER_MODE_WO_BITMAP:
drawOnCanvas(canvas);
break;
case RENDER_MODE_WITH_BITMAP:
canvas.drawBitmap(bitmap, 0f, 0f, paint);
break;
default:
throw new UnsupportedOperationException("Undefined render mode: " + renderMode);
}
}
private Bitmap assembleNewBitmap(int w, int h) {
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawOnCanvas(canvas);
return bitmap;
}
private void drawOnCanvas(@NonNull Canvas canvas) {
canvas.save();
canvas.scale(DISTORTION_FACTOR, DISTORTION_FACTOR);
canvas.drawPath(path, paint);
canvas.restore();
}
}
Full example
I can't understand the quality difference with these two cases. For me it seems that they have to be interchangeable.
Poor quality during scaling is a limitation of Hardware Acceleration according to Android docs.
After seeing your question, I decided to check out the source code of the GLES20RecordingCanvas
class. And here's what I found out:
GLES20RecordingCanvas
extends from GLES20Canvas
which extends from HardwareCanvas
. This HardwareCanvas
class extends from Canvas
. But the main difference I noticed is that it overrides the isHardwareAcceleratedMethod()
returning true.
So my assumption is that the GLES20RecordingCanvas
renders the bitmap with Hardware Acceleration while Canvas doesn't. And this is probably why you get less quality with the GLES20RecorgingCanvas
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With