为什么在缩放 GLES20RecordingCanvas 和简单 Canvas 上绘制的路径具有不同的质量?
Why path drawn on scaled GLES20RecordingCanvas and simple Canvas has different qualities?
按比例绘制的路径 GLES20RecordingCanvas
的质量就像在位图中未按比例绘制然后按比例绘制一样。
相比之下,如果我使用支持位图创建 Canvas
,然后将相同的缩放转换应用到 Canvas
对象,我会得到更好的位图。
这里两个圆都是用 Path.addCircle
和 Canvas.scale
绘制的。上圆是用缩放 GLES20RecordingCanvas
绘制的,下圆是用缩放简单 Canvas
绘制的,带有支持位图。
一些代码:
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();
}
}
我无法理解这两种情况的质量差异。对我来说,它们似乎必须可以互换。
看到你的问题后,我决定查看 GLES20RecordingCanvas
class 的源代码。这是我发现的:
GLES20RecordingCanvas
扩展自 GLES20Canvas
,后者扩展自 HardwareCanvas
。此 HardwareCanvas
class 从 Canvas
延伸而来。但我注意到的主要区别是它覆盖了返回 true 的 isHardwareAcceleratedMethod()
。
所以我的假设是 GLES20RecordingCanvas
使用硬件加速渲染位图,而 Canvas 不使用。这可能就是 GLES20RecorgingCanvas
.
质量较差的原因
根据 Android docs。
,缩放期间质量差是硬件加速的限制
按比例绘制的路径 GLES20RecordingCanvas
的质量就像在位图中未按比例绘制然后按比例绘制一样。
相比之下,如果我使用支持位图创建 Canvas
,然后将相同的缩放转换应用到 Canvas
对象,我会得到更好的位图。
Path.addCircle
和 Canvas.scale
绘制的。上圆是用缩放 GLES20RecordingCanvas
绘制的,下圆是用缩放简单 Canvas
绘制的,带有支持位图。
一些代码:
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();
}
}
我无法理解这两种情况的质量差异。对我来说,它们似乎必须可以互换。
看到你的问题后,我决定查看 GLES20RecordingCanvas
class 的源代码。这是我发现的:
GLES20RecordingCanvas
扩展自 GLES20Canvas
,后者扩展自 HardwareCanvas
。此 HardwareCanvas
class 从 Canvas
延伸而来。但我注意到的主要区别是它覆盖了返回 true 的 isHardwareAcceleratedMethod()
。
所以我的假设是 GLES20RecordingCanvas
使用硬件加速渲染位图,而 Canvas 不使用。这可能就是 GLES20RecorgingCanvas
.
根据 Android docs。
,缩放期间质量差是硬件加速的限制