Почему путь, нарисованный на масштабированной GLES20RecordingCanvas и простой холст, имеет разные качества?

Путь, нарисованный на масштабированном 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();
    }
}

Полный пример

Я не могу понять разницу в качестве этих двух случаев. Мне кажется, что они должны быть взаимозаменяемыми.

Ответ 1

Плохое качество при масштабировании - это ограничение аппаратного ускорения в соответствии с Android docs.

Ответ 2

После просмотра вашего вопроса я решил проверить исходный код класса GLES20RecordingCanvas. И вот что я узнал:

GLES20RecordingCanvas продолжается от GLES20Canvas, который простирается от HardwareCanvas. Этот класс HardwareCanvas распространяется от Canvas. Но основное отличие, которое я заметил, это то, что он отменяет возврат isHardwareAcceleratedMethod() true.

Итак, мое предположение состоит в том, что GLES20RecordingCanvas отображает растровое изображение с аппаратным ускорением, а Canvas - нет. Вероятно, поэтому вы получаете меньше качества с помощью GLES20RecorgingCanvas.