5

我的应用程序使用我缩放的画布,以便我可以以米而不是像素为单位指定路径点。当我缩放画布,然后使用 绘制一条线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();
        }
    }
}

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

截图.png

硬件是 1024x768 平板电脑,运行 android 4.1.1。处理器是瑞芯微RK30。

我的偏好是使用带硬件加速的路径,用于点和速度之间的圆角连接。如果我做错了什么来造成这个问题,请告诉我。谢谢

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

4

3 回答 3

8

This is a limitation of the hardware accelerated renderer. Paths are rasterized at their native size before transform. In your case, the Path is transformed into a 1x4 texture. That texture is then scaled at draw time. To work around this, scale your Path directly by using Path.transform(Matrix). You can also use scaled coordinates when building the path.

于 2013-04-18T19:22:20.083 回答
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();
}
于 2013-04-19T17:43:15.000 回答
2

我发现解决此问题的另一种方法是将Paths 绘制到另一个Canvas由缓存位图支持的位置,然后将该位图绘制到传递的Canvas. 这消除了我的情况中的模糊和偏移。

于 2013-08-13T18:49:54.500 回答