画布在硬件加速下缩放时的模糊偏移路径

Mar*_*ard 3 graphics android hardware-acceleration

我的应用程序使用我缩放的画布,以便我可以指定以米为单位而不是像素的路径点.当我缩放画布时,然后使用path.lineTo()硬键加速画线,线条模糊和偏移.关闭或使用硬件加速时不会发生这种情况canvas.drawLine().

以下是重现问题的代码:

package com.example.canvasproblem;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(new MyView(this));
    }

    class MyView extends View {
        Paint pen = new Paint();
        public MyView(Context context) {
            super(context);
            pen.setStyle(Paint.Style.STROKE);
            pen.setStrokeWidth(1f); // 1 meters wide
            //this.setLayerType(LAYER_TYPE_SOFTWARE, null);
        }
        protected void onDraw(Canvas canvas) {
            float width_meter = 10.0f; // width of canvas in meters
            float width_pxl = canvas.getWidth(); // width of canvas in pixels
            float height_pxl = canvas.getHeight(); // height of canvas in pixels

            canvas.save();
            canvas.translate(width_pxl/2, height_pxl/2); // make center of canvas (0,0)
            canvas.scale(width_pxl/width_meter, width_pxl/width_meter); // convert to meters

            // path
            Path path = new Path();
            path.moveTo(0, 0);
            path.lineTo(0, 4);
            canvas.drawPath(path, pen);

            // line
            canvas.drawLine(0, 0, 0, 4, pen);

            canvas.restore();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是问题输出的屏幕截图(正确的drawLine()显示在lineTo()的顶部):

Screenshot.png

硬件是1024x768平板电脑,运行android 4.1.1.处理器是Rockchip RK30.

我的偏好是使用Path的硬件加速,用于点和速度之间的圆形连接.如果我做错了什么来创建这个问题,请告诉我.谢谢

温柔,这是我的第一篇文章.

Rom*_*Guy 6

这是硬件加速渲染器的限制.在变换之前,路径以其原始大小进行栅格化.在您的情况下,Path将转换为1x4纹理.然后在绘制时缩放该纹理.要解决此问题,请使用直接缩放Path Path.transform(Matrix).您还可以在构建路径时使用缩放坐标.

  • 7 年后对此答案的更新...文档已更新,以指定在什么 API 级别下支持哪些缩放操作:https://developer.android.com/guide/topics/graphics/hardware-accel#scaling 本文档建议路径缩放在 Android 28(Pie,2018 年发布)中得到修复。 (2认同)

Mar*_*ard 5

感谢Romain Guy的回答,这是drawPath()方法的包装器,该方法为打开和关闭硬件加速产生相同的结果。它仅处理现有矩阵中x和y缩放比例相同的情况,并且可能不是最有效的。

void drawPath(Canvas canvas, Path path, final Paint pen) {
    canvas.save();

    // get the current matrix
    Matrix mat = canvas.getMatrix();

    // reverse the effects of the current matrix
    Matrix inv = new Matrix();
    mat.invert(inv);
    canvas.concat(inv);

    // transform the path
    path.transform(mat);

    // get the scale for transforming the Paint
    float[] pts = {0, 0, 1, 0}; // two points 1 unit away from each other
    mat.mapPoints(pts);
    float scale = (float) Math.sqrt(Math.pow(pts[0]-pts[2], 2) + Math.pow(pts[1]-pts[3], 2));

    // copy the existing Paint
    Paint pen2 = new Paint();
    pen2.set(pen);

    // scale the Paint
    pen2.setStrokeMiter(pen.getStrokeMiter()*scale);
    pen2.setStrokeWidth(pen.getStrokeWidth()*scale);

    // draw the path
    canvas.drawPath(path, pen2);

    canvas.restore();
}
Run Code Online (Sandbox Code Playgroud)