为什么在缩放 GLES20RecordingCanvas 和简单 Canvas 上绘制的路径具有不同的质量?

Why path drawn on scaled GLES20RecordingCanvas and simple Canvas has different qualities?

按比例绘制的路径 GLES20RecordingCanvas 的质量就像在位图中未按比例绘制然后按比例绘制一样。

相比之下,如果我使用支持位图创建 Canvas,然后将相同的缩放转换应用到 Canvas 对象,我会得到更好的位图。

这里两个圆都是用 Path.addCircleCanvas.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();
    }
}

Full example

我无法理解这两种情况的质量差异。对我来说,它们似乎必须可以互换。

看到你的问题后,我决定查看 GLES20RecordingCanvas class 的源代码。这是我发现的:

GLES20RecordingCanvas 扩展自 GLES20Canvas,后者扩展自 HardwareCanvas。此 HardwareCanvas class 从 Canvas 延伸而来。但我注意到的主要区别是它覆盖了返回 true 的 isHardwareAcceleratedMethod()

所以我的假设是 GLES20RecordingCanvas 使用硬件加速渲染位图,而 Canvas 不使用。这可能就是 GLES20RecorgingCanvas.

质量较差的原因

根据 Android docs

,缩放期间质量差是硬件加速的限制