My application uses a canvas that I scale so that I can specify path points in meters instead of pixels. When I scale the canvas, then draw a line using path.lineTo()<
Another way to get around this issue as I've found is to draw the Path
s to another Canvas
that is backed by a cache bitmap, and then draw that bitmap to the passed Canvas
. This eliminates the blurring and offsets in my situation.
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.
Thanks to Romain Guy's answer, here is a wrapper for the drawPath() method that produces the same results for hardware acceleration on and off. It only handles the case where the x & y scaling in the existing matrix are the same, and it might not be the most efficient.
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();
}